Skip to content

Commit bd3cf48

Browse files
authored
Merge pull request #534 from lowcoder-org/dev
Take the latest changes from Raheel
2 parents 8d7d71f + b4e12f2 commit bd3cf48

File tree

14 files changed

+194
-64
lines changed

14 files changed

+194
-64
lines changed

client/packages/lowcoder/src/appView/AppViewInstance.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { AppView } from "./AppView";
1111
import { API_STATUS_CODES } from "constants/apiConstants";
1212
import { AUTH_LOGIN_URL } from "constants/routesURL";
1313
import { AuthSearchParams } from "constants/authConstants";
14+
import { saveAuthSearchParams } from "@lowcoder-ee/pages/userAuth/authUtils";
1415

1516
export type OutputChangeHandler<O> = (output: O) => void;
1617
export type EventTriggerHandler = (eventName: string) => void;
@@ -71,9 +72,11 @@ export class AppViewInstance<I = any, O = any> {
7172
.then((i) => i.data)
7273
.catch((e) => {
7374
if (e.response?.status === API_STATUS_CODES.REQUEST_NOT_AUTHORISED) {
74-
window.location.href = `${webUrl}${AUTH_LOGIN_URL}?${
75-
AuthSearchParams.redirectUrl
76-
}=${encodeURIComponent(window.location.href)}`;
75+
saveAuthSearchParams({
76+
[AuthSearchParams.redirectUrl]: encodeURIComponent(window.location.href),
77+
[AuthSearchParams.loginType]: null,
78+
})
79+
window.location.href = `${webUrl}${AUTH_LOGIN_URL}`;
7780
}
7881
});
7982

client/packages/lowcoder/src/comps/hooks/hookComp.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import { ThemeComp } from "./themeComp";
3333
import UrlParamsHookComp from "./UrlParamsHookComp";
3434
import { UtilsComp } from "./utilsComp";
3535
import { VideoMeetingControllerComp } from "../comps/meetingComp/videoMeetingControllerComp";
36+
import { ScreenInfoHookComp } from "./screenInfoComp";
3637

3738
window._ = _;
3839
window.dayjs = dayjs;
@@ -97,6 +98,7 @@ const HookMap: HookCompMapRawType = {
9798
modal: ModalComp,
9899
meeting: VideoMeetingControllerComp,
99100
currentUser: CurrentUserHookComp,
101+
screenInfo: ScreenInfoHookComp,
100102
urlParams: UrlParamsHookComp,
101103
drawer: DrawerComp,
102104
theme: ThemeComp,

client/packages/lowcoder/src/comps/hooks/hookCompTypes.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ const AllHookComp = [
1414
"message",
1515
"localStorage",
1616
"currentUser",
17+
"screenInfo",
1718
"urlParams",
1819
"theme",
1920
] as const;

client/packages/lowcoder/src/comps/hooks/hookListComp.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ const defaultHookListValue = [
2121
{ compType: "message", name: "message" },
2222
{ compType: "localStorage", name: "localStorage" },
2323
{ compType: "currentUser", name: "currentUser" },
24+
{ compType: "screenInfo", name: "screenInfo" },
2425
{ compType: "theme", name: "theme" },
2526
] as const;
2627

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import { useCallback, useEffect, useState } from "react";
2+
import { hookToStateComp } from "../generators/hookToComp";
3+
4+
enum ScreenTypes {
5+
Mobile = 'mobile',
6+
Tablet = 'tablet',
7+
Desktop = 'desktop',
8+
}
9+
10+
type ScreenType = typeof ScreenTypes[keyof typeof ScreenTypes]
11+
12+
type ScreenInfo = {
13+
width?: number;
14+
height?: number;
15+
deviceType?: ScreenType;
16+
isDesktop?: boolean;
17+
isTablet?: boolean;
18+
isMobile?: boolean;
19+
}
20+
21+
function useScreenInfo() {
22+
const getDeviceType = () => {
23+
if (window.screen.width < 768) return ScreenTypes.Mobile;
24+
if (window.screen.width < 889) return ScreenTypes.Tablet;
25+
return ScreenTypes.Desktop;
26+
}
27+
const getFlagsByDeviceType = (deviceType: ScreenType) => {
28+
const flags = {
29+
isMobile: false,
30+
isTablet: false,
31+
isDesktop: false,
32+
};
33+
if(deviceType === ScreenTypes.Mobile) {
34+
return { ...flags, isMobile: true };
35+
}
36+
if(deviceType === ScreenTypes.Tablet) {
37+
return { ...flags, Tablet: true };
38+
}
39+
return { ...flags, isDesktop: true };
40+
}
41+
42+
const getScreenInfo = useCallback(() => {
43+
const { width, height } = window.screen;
44+
const deviceType = getDeviceType();
45+
const flags = getFlagsByDeviceType(deviceType);
46+
47+
return { width, height, deviceType, ...flags };
48+
}, [])
49+
50+
const [screenInfo, setScreenInfo] = useState<ScreenInfo>({});
51+
52+
const updateScreenInfo = useCallback(() => {
53+
setScreenInfo(getScreenInfo());
54+
}, [getScreenInfo])
55+
56+
useEffect(() => {
57+
window.addEventListener('resize', updateScreenInfo);
58+
updateScreenInfo();
59+
return () => window.removeEventListener('resize', updateScreenInfo);
60+
}, [ updateScreenInfo ])
61+
62+
return screenInfo;
63+
}
64+
65+
export const ScreenInfoHookComp = hookToStateComp(useScreenInfo);

client/packages/lowcoder/src/constants/authConstants.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,14 @@ import {
2222
export type AuthInviteInfo = InviteInfo & { invitationId: string };
2323
export type AuthLocationState = { inviteInfo?: AuthInviteInfo; thirdPartyAuthError?: boolean };
2424

25-
export const AuthSearchParams = {
26-
loginType: "loginType",
27-
redirectUrl: "redirectUrl",
25+
export enum AuthSearchParams {
26+
loginType = "loginType",
27+
redirectUrl = "redirectUrl",
28+
};
29+
30+
export type AuthSearchParamsType = {
31+
loginType: string | null,
32+
redirectUrl: string | null,
2833
};
2934

3035
export type OauthRequestParam = {

client/packages/lowcoder/src/constants/routesURL.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ export const QR_CODE_OAUTH_URL = `${USER_AUTH_URL}/oauth/qrcode`;
3939
export const OAUTH_REDIRECT = `${USER_AUTH_URL}/oauth/redirect`;
4040
export const CAS_AUTH_REDIRECT = `${USER_AUTH_URL}/cas/redirect`;
4141
export const LDAP_AUTH_LOGIN_URL = `${USER_AUTH_URL}/ldap/login`;
42-
export const USER_INFO_COMPLETION = `${USER_AUTH_URL}/completion`;
4342
export const INVITE_LANDING_URL = "/invite/:invitationId";
4443
export const ORG_AUTH_LOGIN_URL = `/org/:orgId/auth/login`;
4544
export const ORG_AUTH_REGISTER_URL = `/org/:orgId/auth/register`;

client/packages/lowcoder/src/pages/editor/right/uiCompPanel.tsx

Lines changed: 75 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,23 @@ import { draggingUtils } from "layout";
88
import { isEmpty } from "lodash";
99
import { language } from "i18n";
1010
import {
11-
ComListTitle,
1211
CompIconDiv,
1312
EmptyCompContent,
1413
RightPanelContentWrapper,
1514
} from "pages/editor/right/styledComponent";
1615
import { tableDragClassName } from "pages/tutorials/tutorialsConstant";
17-
import React, { useContext, useMemo } from "react";
16+
import React, { useContext, useMemo, useState } from "react";
1817
import styled from "styled-components";
19-
import { labelCss } from "lowcoder-design";
18+
import {
19+
BaseSection,
20+
PropertySectionContext,
21+
PropertySectionContextType,
22+
PropertySectionState,
23+
labelCss,
24+
} from "lowcoder-design";
2025
import { TransparentImg } from "../../../util/commonUtils";
2126
import { RightContext } from "./rightContext";
2227

23-
const GrayLabel = (props: { label: string }) => {
24-
const { label } = props;
25-
return <ComListTitle>{label}</ComListTitle>;
26-
};
27-
2828
const CompDiv = styled.div`
2929
display: flex;
3030
flex-direction: column;
@@ -80,16 +80,25 @@ const InsertContain = styled.div`
8080
gap: 8px;
8181
`;
8282

83-
const CategoryLabel = styled(GrayLabel)`
84-
margin: 0;
85-
`;
86-
8783
const SectionWrapper = styled.div`
88-
margin-bottom: 16px;
84+
.section-header {
85+
margin-left: 0;
86+
}
87+
&:not(:last-child){
88+
border-bottom: 1px solid #e1e3eb;
89+
}
8990
`;
9091

92+
const stateCompName = 'UICompSections';
93+
const initialState: PropertySectionState = { [stateCompName]: {}};
94+
Object.keys(uiCompCategoryNames).forEach((cat) => {
95+
const key = uiCompCategoryNames[cat as UICompCategory];
96+
initialState[stateCompName][key] = key === uiCompCategoryNames.common
97+
})
98+
9199
export const UICompPanel = () => {
92100
const { onDrag, searchValue } = useContext(RightContext);
101+
const [propertySectionState, setPropertySectionState] = useState<PropertySectionState>(initialState);
93102

94103
const categories = useMemo(() => {
95104
const cats: Record<string, [string, UICompManifest][]> = Object.fromEntries(
@@ -103,6 +112,22 @@ export const UICompPanel = () => {
103112
return cats;
104113
}, []);
105114

115+
const propertySectionContextValue = useMemo<PropertySectionContextType>(() => {
116+
return {
117+
compName: stateCompName,
118+
state: propertySectionState,
119+
toggle: (compName: string, sectionName: string) => {
120+
setPropertySectionState((oldState) => {
121+
const nextSectionState: PropertySectionState = { ...oldState };
122+
const compState = nextSectionState[compName] || {};
123+
compState[sectionName] = compState[sectionName] === false;
124+
nextSectionState[compName] = compState;
125+
return nextSectionState;
126+
});
127+
},
128+
};
129+
}, [propertySectionState]);
130+
106131
const compList = useMemo(
107132
() =>
108133
Object.entries(categories)
@@ -122,36 +147,52 @@ export const UICompPanel = () => {
122147

123148
return (
124149
<SectionWrapper key={index}>
125-
<CategoryLabel label={uiCompCategoryNames[key as UICompCategory]} />
126-
<InsertContain>
127-
{infos.map((info) => (
128-
<CompDiv key={info[0]} className={info[0] === "table" ? tableDragClassName : ""}>
129-
<HovDiv
130-
draggable
131-
onDragStart={(e) => {
132-
e.dataTransfer.setData("compType", info[0]);
133-
e.dataTransfer.setDragImage(TransparentImg, 0, 0);
134-
draggingUtils.setData("compType", info[0]);
135-
onDrag(info[0]);
136-
}}
137-
>
138-
<IconContain Icon={info[1].icon}></IconContain>
139-
</HovDiv>
140-
<CompNameLabel>{info[1].name}</CompNameLabel>
141-
{language !== "en" && <CompEnNameLabel>{info[1].enName}</CompEnNameLabel>}
142-
</CompDiv>
143-
))}
144-
</InsertContain>
150+
<BaseSection
151+
noMargin
152+
width={288}
153+
name={uiCompCategoryNames[key as UICompCategory]}
154+
>
155+
<InsertContain>
156+
{infos.map((info) => (
157+
<CompDiv key={info[0]} className={info[0] === "table" ? tableDragClassName : ""}>
158+
<HovDiv
159+
draggable
160+
onDragStart={(e) => {
161+
e.dataTransfer.setData("compType", info[0]);
162+
e.dataTransfer.setDragImage(TransparentImg, 0, 0);
163+
draggingUtils.setData("compType", info[0]);
164+
onDrag(info[0]);
165+
}}
166+
>
167+
<IconContain Icon={info[1].icon}></IconContain>
168+
</HovDiv>
169+
<CompNameLabel>{info[1].name}</CompNameLabel>
170+
{language !== "en" && <CompEnNameLabel>{info[1].enName}</CompEnNameLabel>}
171+
</CompDiv>
172+
))}
173+
</InsertContain>
174+
</BaseSection>
145175
</SectionWrapper>
146176
);
147177
})
148178
.filter((t) => t != null),
149179
[categories, searchValue, onDrag]
150180
);
151181

182+
if(!compList.length) return (
183+
<RightPanelContentWrapper>
184+
<EmptyCompContent />
185+
</RightPanelContentWrapper>
186+
)
187+
152188
return (
153189
<RightPanelContentWrapper>
154-
{compList.length > 0 ? compList : <EmptyCompContent />}
190+
{/* {compList.length > 0 ? compList : <EmptyCompContent />} */}
191+
<PropertySectionContext.Provider
192+
value={propertySectionContextValue}
193+
>
194+
{compList}
195+
</PropertySectionContext.Provider>
155196
</RightPanelContentWrapper>
156197
);
157198
};

client/packages/lowcoder/src/pages/userAuth/authUtils.ts

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import {
33
BASE_URL,
44
CAS_AUTH_REDIRECT,
55
OAUTH_REDIRECT,
6-
USER_INFO_COMPLETION,
76
} from "constants/routesURL";
87
import { AxiosPromise, AxiosResponse } from "axios";
98
import { ApiResponse } from "api/apiResponses";
@@ -16,6 +15,7 @@ import { createContext, useState } from "react";
1615
import { SystemConfig } from "constants/configConstants";
1716
import {
1817
AuthInviteInfo,
18+
AuthSearchParamsType,
1919
AuthSessionStoreParams,
2020
ThirdPartyAuthGoal,
2121
ThirdPartyAuthType,
@@ -79,12 +79,7 @@ export function authRespValidate(
7979
) {
8080
let replaceUrl = redirectUrl || BASE_URL;
8181
const baseUrl = `${window.location.protocol}//${window.location.host}`;
82-
if (infoCompleteCheck) {
83-
// need complete info
84-
replaceUrl = redirectUrl
85-
? `${USER_INFO_COMPLETION}?redirectUrl=${redirectUrl}`
86-
: USER_INFO_COMPLETION;
87-
}
82+
8883
if (doValidResponse(resp)) {
8984
onAuthSuccess?.();
9085
history.replace(replaceUrl.replace(baseUrl, ''));
@@ -185,3 +180,21 @@ export const getRedirectUrl = (authType: ThirdPartyAuthType) => {
185180
`${window.location.origin}${authType === "CAS" ? CAS_AUTH_REDIRECT : OAUTH_REDIRECT}`
186181
);
187182
};
183+
184+
const AuthSearchParamStorageKey = "_temp_auth_search_params_";
185+
186+
export const saveAuthSearchParams = (
187+
authSearchParams: AuthSearchParamsType
188+
) => {
189+
sessionStorage.setItem(AuthSearchParamStorageKey, JSON.stringify(authSearchParams));
190+
}
191+
192+
export const loadAuthSearchParams = ():AuthSearchParamsType | null => {
193+
const authParams = sessionStorage.getItem(AuthSearchParamStorageKey);
194+
if (!authParams) return null;
195+
return JSON.parse(authParams);
196+
}
197+
198+
export const clearAuthSearchParams = () => {
199+
sessionStorage.removeItem(AuthSearchParamStorageKey);
200+
}

client/packages/lowcoder/src/pages/userAuth/index.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { Redirect, Route, Switch, useLocation, useParams } from "react-router-do
33
import React, { useEffect, useMemo } from "react";
44
import { useSelector, useDispatch } from "react-redux";
55
import { selectSystemConfig } from "redux/selectors/configSelectors";
6-
import { AuthContext } from "pages/userAuth/authUtils";
6+
import { AuthContext, clearAuthSearchParams } from "pages/userAuth/authUtils";
77
import { AuthRoutes } from "@lowcoder-ee/constants/authConstants";
88
import { AuthLocationState } from "constants/authConstants";
99
import { ProductLoading } from "components/ProductLoading";
@@ -37,6 +37,7 @@ export default function UserAuth() {
3737

3838
const fetchUserAfterAuthSuccess = () => {
3939
dispatch(fetchUserAction());
40+
clearAuthSearchParams();
4041
}
4142

4243
return (

client/packages/lowcoder/src/pages/userAuth/thirdParty/authenticator/abstractAuthenticator.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ export abstract class AbstractAuthenticator {
3939
authRespValidate(
4040
resp,
4141
this.needInfoCheck(this.authParams.sourceType),
42-
this.authParams.afterLoginRedirect,
42+
getSafeAuthRedirectURL(this.authParams.afterLoginRedirect),
4343
onAuthSuccess,
4444
);
4545
})

0 commit comments

Comments
 (0)