Web:Client:OAUth: add preview

This commit is contained in:
Timofey Boyko 2023-09-28 14:36:53 +03:00
parent f6dca051ac
commit a34bedef1e
4 changed files with 315 additions and 131 deletions

View File

@ -1,6 +1,32 @@
import styled from "styled-components";
//@ts-ignore
import Box from "@docspace/components/box";
import { hugeMobile, tablet } from "@docspace/components/utils/device";
const Container = styled.div`
width: 100%;
display: grid;
grid-template-columns: 350px 350px;
gap: 16px;
.preview-container {
margin-top: 16px;
width: fit-content;
min-width: 350px;
height: fit-content;
border: 1px solid #a3aeae;
border-radius: 6px;
padding: 16px;
}
`;
const FormContainer = styled.div`
max-width: 350px;
display: flex;
@ -85,12 +111,51 @@ const CheckboxRaw = styled.div`
}
`;
const Frame = styled(Box)`
margin-top: 16px;
position: relative;
display: flex;
justify-content: center;
button {
width: auto;
max-width: auto;
padding: 0 20px;
}
`;
const CategorySubHeader = styled.div`
margin-top: 8px;
margin-bottom: 8px;
font-size: 15px;
font-style: normal;
font-weight: 600;
line-height: 16px;
@media ${tablet} {
&:not(&.copy-window-code) {
margin-bottom: 0;
}
}
@media ${hugeMobile} {
&:first-of-type {
margin-top: 0;
}
}
`;
export {
Container,
FormContainer,
BlockContainer,
HeaderRaw,
InputGroup,
InputRaw,
CheckboxGroup,
CheckboxRaw,
Frame,
CategorySubHeader,
};

View File

@ -54,3 +54,9 @@ export interface ClientFormProps {
regenerateSecret?: (clientId: string) => Promise<string>;
}
export interface PreviewProps {
clientId: string;
redirectURI: string;
scopes: string[];
}

View File

@ -0,0 +1,98 @@
import React from "react";
//@ts-ignore
import Loaders from "@docspace/common/components/Loaders";
//@ts-ignore
import Box from "@docspace/components/box";
//@ts-ignore
import Textarea from "@docspace/components/textarea";
//@ts-ignore
import TabContainer from "@docspace/components/tabs-container";
//@ts-ignore
import SocialButton from "@docspace/components/social-button";
import ImagesLogoSvgUrl from "PUBLIC_DIR/images/logo/leftmenu.svg?url";
import { PreviewProps } from "../ClientForm.types";
import { Frame, CategorySubHeader } from "../ClientForm.styled";
const Preview = ({ clientId, redirectURI, scopes }: PreviewProps) => {
const getAuthLink = () => {
const origin = window.location.origin;
const path = "/oauth2/authorize";
const params: { [key: string]: string } = {
response_type: "code",
client_id: clientId,
redirect_uri: redirectURI,
scope: scopes[0],
code_challenge_method: "S256",
code_challenge: "ZX8YUY6qL0EweJXhjDug0S2XuKI8beOWb1LGujmgfuQ",
};
const paramsString = [];
for (let key in params) {
const str = `${key}=${params[key]}`;
paramsString.push(str);
}
const link = `${origin}${path}?${paramsString.join("&")}`;
return link;
};
const onDocSpaceLogin = () => {
const url = getAuthLink();
window.open(
url,
"login",
"width=800,height=500,status=no,toolbar=no,menubar=no,resizable=yes,scrollbars=no"
);
};
const preview = (
<Frame>
<SocialButton
iconName={ImagesLogoSvgUrl}
label={"Sign in with DocSpace"}
onClick={onDocSpaceLogin}
/>
</Frame>
);
const codeBlock = "123";
const code = (
<>
<CategorySubHeader className="copy-window-code">
{"Copy window code"}
</CategorySubHeader>
<Textarea value={codeBlock} />
</>
);
const dataTabs = [
{
key: "preview",
title: "Preview",
content: preview,
},
{
key: "code",
title: "Code",
content: code,
},
];
return (
<div className="preview-container">
<TabContainer elements={dataTabs} />
</div>
);
};
export default Preview;

View File

@ -17,8 +17,14 @@ import { OAuthStoreProps } from "SRC_DIR/store/OAuthStore";
import CheckboxComponent from "./components/Checkbox";
import { CheckboxGroup, Container, InputGroup } from "./ClientForm.styled";
import {
Container,
FormContainer,
CheckboxGroup,
InputGroup,
} from "./ClientForm.styled";
import { ClientFormProps } from "./ClientForm.types";
import Preview from "./components/Preview";
const ClientForm = ({
id,
@ -255,160 +261,169 @@ const ClientForm = ({
return (
<Container>
<Block>
<BlockHeader header={"Basic info"} helpButtonText="" />
<InputGroup>
<InputHeader header={"App name"} />
<Input
value={form.appName}
name={"appName"}
placeholder={"Enter name"}
onChange={onInputChange}
/>
</InputGroup>
<InputGroup>
<InputHeader header={"App icon"} />
<Input
value={form.appIcon}
name={"appIcon"}
placeholder={"Add icon"}
onChange={onInputChange}
/>
</InputGroup>
<InputGroup>
<InputHeader header={"Description"} />
<Input
value={form.description}
name={"description"}
placeholder={"Enter description"}
onChange={onInputChange}
/>
</InputGroup>
</Block>
{id && (
<FormContainer>
<Block>
<BlockHeader header={"Client"} helpButtonText="" />
<BlockHeader header={"Basic info"} helpButtonText="" />
<InputGroup>
<InputHeader header={"ID"} />
<InputHeader header={"App name"} />
<Input
value={clientId}
name={"ID"}
placeholder={"Enter id"}
value={form.appName}
name={"appName"}
placeholder={"Enter name"}
onChange={onInputChange}
isReadOnly
withCopy
/>
</InputGroup>
<InputGroup>
<InputHeader header={"Secret"} />
<InputHeader header={"App icon"} />
<Input
value={secret}
name={"secret"}
placeholder={"Enter secret"}
value={form.appIcon}
name={"appIcon"}
placeholder={"Add icon"}
onChange={onInputChange}
isReadOnly
isSecret
withCopy
withButton
buttonLabel="Reset"
onClickButton={onResetClick}
/>
</InputGroup>
<InputGroup>
<InputHeader header={"Authentication method "} />
<InputHeader header={"Description"} />
<Input
value={form.authenticationMethod}
name={"authenticationMethod"}
placeholder={"Enter secret"}
value={form.description}
name={"description"}
placeholder={"Enter description"}
onChange={onInputChange}
isReadOnly
withCopy
/>
</InputGroup>
</Block>
)}
<Block>
<BlockHeader header={"OAuth URLs"} helpButtonText="" />
<InputGroup>
<InputHeader header={"Redirect url"} />
<Input
value={form.redirectUrl}
name={"redirectUrl"}
placeholder={"Enter URL"}
onChange={onInputChange}
/>
</InputGroup>
<InputGroup>
<InputHeader header={"Logout redirect url"} />
<Input
value={form.logoutRedirectUrl}
name={"logoutRedirectUrl"}
placeholder={"Enter URL"}
onChange={onInputChange}
/>
</InputGroup>
</Block>
<Block>
<BlockHeader header={"Access scopes"} helpButtonText="" />
<CheckboxGroup>
{scopes.length > 0 &&
scopes.map((scope) => (
<CheckboxComponent
key={`${scope.name}`}
isChecked={checkedScopes.includes(scope.name)}
onChange={() => onCheckboxChange(scope.name)}
label={scope.name}
description={scope.description}
{id && (
<Block>
<BlockHeader header={"Client"} helpButtonText="" />
<InputGroup>
<InputHeader header={"ID"} />
<Input
value={clientId}
name={"ID"}
placeholder={"Enter id"}
onChange={onInputChange}
isReadOnly
withCopy
/>
))}
</CheckboxGroup>
</Block>
</InputGroup>
<InputGroup>
<InputHeader header={"Secret"} />
<Input
value={secret}
name={"secret"}
placeholder={"Enter secret"}
onChange={onInputChange}
isReadOnly
isSecret
withCopy
withButton
buttonLabel="Reset"
onClickButton={onResetClick}
/>
</InputGroup>
<Block>
<BlockHeader header={"Support & Legal info"} helpButtonText="" />
<InputGroup>
<InputHeader header={"Authentication method "} />
<Input
value={form.authenticationMethod}
name={"authenticationMethod"}
placeholder={"Enter secret"}
onChange={onInputChange}
isReadOnly
withCopy
/>
</InputGroup>
</Block>
)}
<InputGroup>
<InputHeader header={"Privacy policy URL"} />
<Input
value={form.privacyURL}
name={"privacyURL"}
placeholder={"Enter URL"}
onChange={onInputChange}
<Block>
<BlockHeader header={"OAuth URLs"} helpButtonText="" />
<InputGroup>
<InputHeader header={"Redirect url"} />
<Input
value={form.redirectUrl}
name={"redirectUrl"}
placeholder={"Enter URL"}
onChange={onInputChange}
/>
</InputGroup>
<InputGroup>
<InputHeader header={"Logout redirect url"} />
<Input
value={form.logoutRedirectUrl}
name={"logoutRedirectUrl"}
placeholder={"Enter URL"}
onChange={onInputChange}
/>
</InputGroup>
</Block>
<Block>
<BlockHeader header={"Access scopes"} helpButtonText="" />
<CheckboxGroup>
{scopes.length > 0 &&
scopes.map((scope) => (
<CheckboxComponent
key={`${scope.name}`}
isChecked={checkedScopes.includes(scope.name)}
onChange={() => onCheckboxChange(scope.name)}
label={scope.name}
description={scope.description}
/>
))}
</CheckboxGroup>
</Block>
<Block>
<BlockHeader header={"Support & Legal info"} helpButtonText="" />
<InputGroup>
<InputHeader header={"Privacy policy URL"} />
<Input
value={form.privacyURL}
name={"privacyURL"}
placeholder={"Enter URL"}
onChange={onInputChange}
/>
</InputGroup>
<InputGroup>
<InputHeader header={"Terms of Service URL"} />
<Input
value={form.termsURL}
name={"termsURL"}
placeholder={"Enter URL"}
onChange={onInputChange}
/>
</InputGroup>
</Block>
<div className="button-container">
<Button
//@ts-ignore
label={"Save"}
isDisabled={!isValid}
size={"normal"}
primary
scale={isMobileOnly}
onClick={onSaveClick}
/>
</InputGroup>
<InputGroup>
<InputHeader header={"Terms of Service URL"} />
<Input
value={form.termsURL}
name={"termsURL"}
placeholder={"Enter URL"}
onChange={onInputChange}
<Button
//@ts-ignore
label={"Cancel"}
size={"normal"}
scale={isMobileOnly}
onClick={onCancelClick}
/>
</InputGroup>
</Block>
<div className="button-container">
<Button
//@ts-ignore
label={"Save"}
isDisabled={!isValid}
size={"normal"}
primary
scale={isMobileOnly}
onClick={onSaveClick}
</div>
</FormContainer>
{id && (
<Preview
clientId={clientId}
redirectURI={form.redirectUrl}
scopes={checkedScopes}
/>
<Button
//@ts-ignore
label={"Cancel"}
size={"normal"}
scale={isMobileOnly}
onClick={onCancelClick}
/>
</div>
)}
</Container>
);
};