Skip to content

Commit 999a339

Browse files
authored
Merge branch 'dev' into pwa-icon-support
2 parents 1fb070b + 1671585 commit 999a339

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+526
-232
lines changed

client/packages/lowcoder-comps/src/comps/barChartComp/barChartComp.tsx

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ BarChartTmpComp = withViewFn(BarChartTmpComp, (comp) => {
6161
const [chartSize, setChartSize] = useState<ChartSize>();
6262
const firstResize = useRef(true);
6363
const theme = useContext(ThemeContext);
64+
const [chartKey, setChartKey] = useState(0);
65+
const prevRaceMode = useRef<boolean>();
6466
const defaultChartTheme = {
6567
color: chartColorPalette,
6668
backgroundColor: "#fff",
@@ -73,6 +75,16 @@ BarChartTmpComp = withViewFn(BarChartTmpComp, (comp) => {
7375
log.error('theme chart error: ', error);
7476
}
7577

78+
// Detect race mode changes and force chart recreation
79+
const currentRaceMode = comp.children.chartConfig?.children?.comp?.children?.race?.getView();
80+
useEffect(() => {
81+
if (prevRaceMode.current !== undefined && prevRaceMode.current !== currentRaceMode) {
82+
// Force chart recreation when race mode changes
83+
setChartKey(prev => prev + 1);
84+
}
85+
prevRaceMode.current = currentRaceMode;
86+
}, [currentRaceMode]);
87+
7688
const triggerClickEvent = async (dispatch: any, action: CompAction<JSONValue>) => {
7789
await getPromiseAfterDispatch(
7890
dispatch,
@@ -176,10 +188,11 @@ BarChartTmpComp = withViewFn(BarChartTmpComp, (comp) => {
176188
return (
177189
<div ref={containerRef} style={{height: '100%'}}>
178190
<ReactECharts
191+
key={chartKey}
179192
ref={(e) => (echartsCompRef.current = e)}
180193
style={{ height: "100%" }}
181-
notMerge
182-
lazyUpdate
194+
notMerge={!currentRaceMode}
195+
lazyUpdate={!currentRaceMode}
183196
opts={{ locale: getEchartsLocale() }}
184197
option={option}
185198
mode={mode}

client/packages/lowcoder-comps/src/comps/barChartComp/barChartUtils.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,15 @@ export function getEchartsConfig(
201201
animationEasing: 'linear',
202202
animationEasingUpdate: 'linear',
203203
}
204+
} else {
205+
// Ensure proper animation settings when race is disabled
206+
config = {
207+
...config,
208+
animationDuration: 1000,
209+
animationDurationUpdate: 1000,
210+
animationEasing: 'cubicOut',
211+
animationEasingUpdate: 'cubicOut',
212+
}
204213
}
205214
if (props.data.length <= 0) {
206215
// no data
@@ -333,6 +342,21 @@ export function getEchartsConfig(
333342
animationDurationUpdate: 300
334343
},
335344
}
345+
} else {
346+
// Reset axis animations when race is disabled
347+
config = {
348+
...config,
349+
xAxis: {
350+
...config.xAxis,
351+
animationDuration: undefined,
352+
animationDurationUpdate: undefined
353+
},
354+
yAxis: {
355+
...config.yAxis,
356+
animationDuration: undefined,
357+
animationDurationUpdate: undefined
358+
},
359+
}
336360
}
337361
}
338362
// console.log("Echarts transformedData and config", transformedData, config);

client/packages/lowcoder-comps/src/comps/basicChartComp/chartConfigs/barChartConfig.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ export const BarChartConfig = (function () {
5353
type: "bar",
5454
subtype: props.type,
5555
realtimeSort: props.race,
56-
seriesLayoutBy: props.race?'column':undefined,
56+
seriesLayoutBy: props.race?'column':'row',
5757
label: {
5858
show: props.showLabel,
5959
position: "top",

client/packages/lowcoder-core/lib/index.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1692,11 +1692,12 @@ class CodeNode extends AbstractNode {
16921692
// if query is dependent on itself, mark as ready
16931693
if (pathsArr?.[0] === options?.queryName)
16941694
return;
1695+
// TODO: check if this is needed after removing lazy load
16951696
// wait for lazy loaded comps to load before executing query on page load
1696-
if (value && !Object.keys(value).length && paths.size) {
1697-
isFetching = true;
1698-
ready = false;
1699-
}
1697+
// if (value && !Object.keys(value).length && paths.size) {
1698+
// isFetching = true;
1699+
// ready = false;
1700+
// }
17001701
if (_.has(value, IS_FETCHING_FIELD)) {
17011702
isFetching = isFetching || value.isFetching === true;
17021703
}

client/packages/lowcoder-core/src/eval/codeNode.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -176,11 +176,12 @@ export class CodeNode extends AbstractNode<ValueAndMsg<unknown>> {
176176
// if query is dependent on itself, mark as ready
177177
if (pathsArr?.[0] === options?.queryName) return;
178178

179+
// TODO: check if this is needed after removing lazy load
179180
// wait for lazy loaded comps to load before executing query on page load
180-
if (value && !Object.keys(value).length && paths.size) {
181-
isFetching = true;
182-
ready = false;
183-
}
181+
// if (value && !Object.keys(value).length && paths.size) {
182+
// isFetching = true;
183+
// ready = false;
184+
// }
184185
if (_.has(value, IS_FETCHING_FIELD)) {
185186
isFetching = isFetching || value.isFetching === true;
186187
}

client/packages/lowcoder/src/components/DraggableTree/DroppableMenuItem.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ export default function DraggableMenuItem(props: IDraggableMenuItemProps) {
6767
const canDropBefore = checkDroppableFlag(item.canDropBefore, activeNode?.data);
6868
const canDropAfter = checkDroppableFlag(item.canDropAfter, activeNode?.data);
6969

70+
const lastChildNode = items[items.length - 1];
71+
const canDropAfterLastChild = checkDroppableFlag(lastChildNode?.canDropAfter, activeNode?.data);
72+
7073
const dropData: IDropData = {
7174
targetListSize: items.length,
7275
targetPath: dropInAsSub ? [...path, 0] : [...path.slice(0, -1), path[path.length - 1] + 1],
@@ -136,6 +139,15 @@ export default function DraggableMenuItem(props: IDraggableMenuItemProps) {
136139
/>
137140
</Fragment>
138141
))}
142+
{activeNode && canDropAfterLastChild && (
143+
<div style={{ position: "relative" }}>
144+
<DroppablePlaceholder
145+
targetListSize={-1}
146+
path={[...path, items.length]}
147+
disabled={isDragging || disabled}
148+
/>
149+
</div>
150+
)}
139151
</div>
140152
)}
141153
</>

client/packages/lowcoder/src/components/PermissionDialog/DatasourcePermissionDialog.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { DatasourceRole } from "../../api/datasourcePermissionApi";
1313
import { getDataSourcePermissionInfo } from "../../redux/selectors/datasourceSelectors";
1414
import { StyledLoading } from "./commonComponents";
1515
import { PermissionRole } from "./Permission";
16+
import { getUser } from "../../redux/selectors/usersSelectors";
1617

1718
export const DatasourcePermissionDialog = (props: {
1819
datasourceId: string;
@@ -22,6 +23,7 @@ export const DatasourcePermissionDialog = (props: {
2223
const { datasourceId } = props;
2324
const dispatch = useDispatch();
2425
const permissionInfo = useSelector(getDataSourcePermissionInfo)[datasourceId];
26+
const user = useSelector(getUser);
2527

2628
useEffect(() => {
2729
dispatch(fetchDatasourcePermissions({ datasourceId: datasourceId }));
@@ -75,6 +77,8 @@ export const DatasourcePermissionDialog = (props: {
7577
{ label: trans("share.datasourceOwner"), value: PermissionRole.Owner },
7678
]}
7779
permissionItems={permissions}
80+
contextType="organization"
81+
organizationId={user.currentOrgId}
7882
viewBodyRender={(list) => {
7983
if (!permissionInfo) {
8084
return <StyledLoading size={18} />;

client/packages/lowcoder/src/components/PermissionDialog/Permission.tsx

Lines changed: 38 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import { EmptyContent } from "pages/common/styledComponent";
2727
import { trans } from "i18n";
2828
import { PermissionItem } from "./PermissionList";
2929
import { currentApplication } from "@lowcoder-ee/redux/selectors/applicationSelector";
30-
import { fetchAvailableGroupsMembers } from "@lowcoder-ee/util/pagination/axios";
30+
import { fetchAvailableGroupsMembers, fetchAvailableOrgGroupsMembers } from "@lowcoder-ee/util/pagination/axios";
3131

3232
const AddAppUserContent = styled.div`
3333
display: flex;
@@ -186,6 +186,13 @@ const AddRoleSelect = styled(StyledRoleSelect)<{ $isVisible: boolean }>`
186186
display: ${(props) => (props.$isVisible ? "unset" : "none")};
187187
`;
188188

189+
type PermissionContextType = "application" | "organization";
190+
191+
type PermissionContextProps = {
192+
contextType: PermissionContextType;
193+
organizationId?: string;
194+
};
195+
189196
type AddAppOptionView = {
190197
type: ApplicationPermissionType;
191198
id: string;
@@ -294,8 +301,10 @@ const PermissionSelector = (props: {
294301
user: User;
295302
filterItems: PermissionItem[];
296303
supportRoles: { label: string; value: PermissionRole }[];
304+
contextType: PermissionContextType;
305+
organizationId?: string;
297306
}) => {
298-
const { selectedItems, setSelectRole, setSelectedItems, user } = props;
307+
const { selectedItems, setSelectRole, setSelectedItems, user, contextType, organizationId } = props;
299308
const [roleSelectVisible, setRoleSelectVisible] = useState(false);
300309
const selectRef = useRef<HTMLDivElement>(null);
301310
const [optionViews, setOptionViews] = useState<AddAppOptionView[]>()
@@ -305,42 +314,41 @@ const PermissionSelector = (props: {
305314

306315
const debouncedUserSearch = useCallback(
307316
debounce((searchTerm: string) => {
308-
if (!application) return;
309-
310317
setIsLoading(true);
311-
fetchAvailableGroupsMembers(application.applicationId, searchTerm).then(res => {
312-
if(res.success) {
313-
setOptionViews(getPermissionOptionView(res.data, props.filterItems))
314-
}
315-
setIsLoading(false);
316-
}).catch(() => {
318+
319+
if (contextType === "application" && application) {
320+
fetchAvailableGroupsMembers(application.applicationId, searchTerm).then(res => {
321+
if(res.success) {
322+
setOptionViews(getPermissionOptionView(res.data, props.filterItems))
323+
}
324+
setIsLoading(false);
325+
}).catch(() => {
326+
setIsLoading(false);
327+
});
328+
} else if (contextType === "organization" && organizationId) {
329+
fetchAvailableOrgGroupsMembers(organizationId, searchTerm).then(res => {
330+
if(res.success) {
331+
setOptionViews(getPermissionOptionView(res.data || [], props.filterItems))
332+
}
333+
setIsLoading(false);
334+
}).catch(() => {
335+
setIsLoading(false);
336+
});
337+
} else {
317338
setIsLoading(false);
318-
});
339+
}
319340
}, 500),
320-
[application, props.filterItems]
341+
[application, props.filterItems, contextType, organizationId]
321342
);
322343

323344
useEffect(() => {
324345
debouncedUserSearch(searchValue);
325-
326346
return () => {
327347
debouncedUserSearch.cancel();
328348
};
329349
}, [searchValue, debouncedUserSearch]);
330350

331-
useEffect(() => {
332-
if (!application) return;
333-
334-
setIsLoading(true);
335-
fetchAvailableGroupsMembers(application.applicationId, "").then(res => {
336-
if(res.success) {
337-
setOptionViews(getPermissionOptionView(res.data, props.filterItems))
338-
}
339-
setIsLoading(false);
340-
}).catch(() => {
341-
setIsLoading(false);
342-
});
343-
}, [application, props.filterItems]);
351+
344352

345353
useEffect(() => {
346354
setRoleSelectVisible(selectedItems.length > 0);
@@ -425,8 +433,8 @@ export const Permission = (props: {
425433
supportRoles: { label: string; value: PermissionRole }[];
426434
onCancel: () => void;
427435
addPermission: (userIds: string[], groupIds: string[], role: string) => void;
428-
}) => {
429-
const { onCancel } = props;
436+
} & PermissionContextProps) => {
437+
const { onCancel, contextType = "application", organizationId } = props;
430438
const user = useSelector(getUser);
431439
const [selectRole, setSelectRole] = useState<ApplicationRoleType>("viewer");
432440
const [selectedItems, setSelectedItems] = useState<PermissionAddEntity[]>([]);
@@ -443,6 +451,8 @@ export const Permission = (props: {
443451
user={user}
444452
filterItems={props.filterItems}
445453
supportRoles={props.supportRoles}
454+
contextType={contextType}
455+
organizationId={organizationId}
446456
/>
447457
<BottomButton>
448458
<TacoButton style={{ marginRight: "8px" }} onClick={onCancel}>

client/packages/lowcoder/src/components/PermissionDialog/PermissionDialog.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,10 @@ export const PermissionDialog = (props: {
5757
) => void;
5858
updatePermission: (permissionId: string, role: string) => void;
5959
deletePermission: (permissionId: string) => void;
60+
contextType?: "application" | "organization";
61+
organizationId?: string;
6062
}) => {
61-
const { supportRoles, permissionItems, visible, onVisibleChange, addPermission, viewBodyRender } =
63+
const { supportRoles, permissionItems, visible, onVisibleChange, addPermission, viewBodyRender, contextType, organizationId } =
6264
props;
6365
const [activeStepKey, setActiveStepKey] = useState("view");
6466

@@ -117,6 +119,8 @@ export const PermissionDialog = (props: {
117119
addPermission={(userIds, groupIds, role) =>
118120
addPermission(userIds, groupIds, role, props.back)
119121
}
122+
contextType={contextType || "application"}
123+
organizationId={organizationId}
120124
/>
121125
),
122126
footerRender: (props) => null,

client/packages/lowcoder/src/comps/comps/buttonComp/buttonComp.tsx

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { BoolCodeControl, StringControl } from "comps/controls/codeControl";
1+
import { BoolCodeControl, StringControl, NumberControl } from "comps/controls/codeControl";
22
import { dropdownControl } from "comps/controls/dropdownControl";
33
import { ButtonEventHandlerControl } from "comps/controls/eventHandlerControl";
44
import { IconControl } from "comps/controls/iconControl";
@@ -137,7 +137,8 @@ const childrenMap = {
137137
disabledStyle: DisabledButtonStyleControl,
138138
animationStyle: styleControl(AnimationStyle, 'animationStyle'),
139139
viewRef: RefControl<HTMLElement>,
140-
tooltip: StringControl
140+
tooltip: StringControl,
141+
tabIndex: NumberControl
141142
};
142143

143144
type ChildrenType = NewChildren<RecordConstructorToComp<typeof childrenMap>>;
@@ -162,8 +163,12 @@ const ButtonPropertyView = React.memo((props: {
162163
disabledPropertyView(props.children),
163164
hiddenPropertyView(props.children),
164165
loadingPropertyView(props.children),
166+
props.children.tabIndex.propertyView({ label: trans("prop.tabIndex") }),
165167
]
166-
: props.children.form.getPropertyView()}
168+
: [
169+
props.children.form.getPropertyView(),
170+
props.children.tabIndex.propertyView({ label: trans("prop.tabIndex") }),
171+
]}
167172
</Section>
168173
</>
169174
)}
@@ -222,6 +227,7 @@ const ButtonView = React.memo((props: ToViewReturn<ChildrenType>) => {
222227
(!isDefault(props.type) && getForm(editorState, props.form)?.disableSubmit())
223228
}
224229
onClick={handleClick}
230+
tabIndex={typeof props.tabIndex === 'number' ? props.tabIndex : undefined}
225231
>
226232
{props.prefixIcon && <IconWrapper>{props.prefixIcon}</IconWrapper>}
227233
{

0 commit comments

Comments
 (0)