Web:Client:OAuth: add row view
This commit is contained in:
parent
807215a0cb
commit
ca73c5b0c4
@ -0,0 +1,85 @@
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
//@ts-ignore
|
||||
import Row from "@docspace/components/row";
|
||||
import ToggleButton from "@docspace/components/toggle-button";
|
||||
|
||||
import { RowContent } from "./RowContent";
|
||||
import { RowProps } from "./RowView.types";
|
||||
|
||||
export const OAuthRow = (props: RowProps) => {
|
||||
const {
|
||||
item,
|
||||
sectionWidth,
|
||||
changeClientStatus,
|
||||
isChecked,
|
||||
inProgress,
|
||||
getContextMenuItems,
|
||||
setSelection,
|
||||
} = props;
|
||||
const navigate = useNavigate();
|
||||
|
||||
const { t } = useTranslation(["Common"]);
|
||||
|
||||
const editClient = () => {
|
||||
navigate(`${item.clientId}`);
|
||||
};
|
||||
|
||||
const handleToggleEnabled = async () => {
|
||||
if (!changeClientStatus) return;
|
||||
await changeClientStatus(item.clientId, !item.enabled);
|
||||
};
|
||||
|
||||
const handleRowClick = (e: any) => {
|
||||
if (
|
||||
e.target.closest(".checkbox") ||
|
||||
e.target.closest(".table-container_row-checkbox") ||
|
||||
e.detail === 0
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
e.target.closest(".table-container_row-context-menu-wrapper") ||
|
||||
e.target.closest(".toggleButton") ||
|
||||
e.target.closest(".row_context-menu-wrapper")
|
||||
) {
|
||||
return setSelection && setSelection("");
|
||||
}
|
||||
|
||||
editClient();
|
||||
};
|
||||
|
||||
const contextOptions = getContextMenuItems && getContextMenuItems(t, item);
|
||||
|
||||
const element = <img src={item.logoUrl} alt={"App logo"} />;
|
||||
|
||||
return (
|
||||
<>
|
||||
<Row
|
||||
sectionWidth={sectionWidth}
|
||||
key={item.clientId}
|
||||
data={item}
|
||||
contextOptions={contextOptions}
|
||||
onClick={handleRowClick}
|
||||
element={element}
|
||||
mode={"modern"}
|
||||
checked={isChecked}
|
||||
inProgress={inProgress}
|
||||
onSelect={() => setSelection && setSelection(item.clientId)}
|
||||
>
|
||||
<RowContent
|
||||
sectionWidth={sectionWidth}
|
||||
item={item}
|
||||
isChecked={isChecked}
|
||||
inProgress={inProgress}
|
||||
setSelection={setSelection}
|
||||
handleToggleEnabled={handleToggleEnabled}
|
||||
/>
|
||||
</Row>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default OAuthRow;
|
@ -0,0 +1,57 @@
|
||||
import React from "react";
|
||||
|
||||
import Text from "@docspace/components/text";
|
||||
|
||||
import ToggleButton from "@docspace/components/toggle-button";
|
||||
|
||||
import { isMobileOnly } from "react-device-detect";
|
||||
|
||||
import {
|
||||
StyledRowContent,
|
||||
ContentWrapper,
|
||||
FlexWrapper,
|
||||
ToggleButtonWrapper,
|
||||
} from "./RowView.styled";
|
||||
import { RowContentProps } from "./RowView.types";
|
||||
|
||||
export const RowContent = ({
|
||||
sectionWidth,
|
||||
item,
|
||||
|
||||
handleToggleEnabled,
|
||||
}: RowContentProps) => {
|
||||
return (
|
||||
<StyledRowContent sectionWidth={sectionWidth}>
|
||||
<ContentWrapper>
|
||||
<FlexWrapper>
|
||||
{/* @ts-ignore */}
|
||||
<Text
|
||||
fontWeight={600}
|
||||
fontSize="14px"
|
||||
style={{ marginInlineEnd: "8px" }}
|
||||
>
|
||||
{item.name}
|
||||
</Text>
|
||||
</FlexWrapper>
|
||||
|
||||
{!isMobileOnly && (
|
||||
<>
|
||||
{/* @ts-ignore */}
|
||||
<Text fontWeight={600} fontSize="12px" color="#A3A9AE">
|
||||
{item.description}
|
||||
</Text>
|
||||
</>
|
||||
)}
|
||||
</ContentWrapper>
|
||||
|
||||
<ToggleButtonWrapper>
|
||||
<ToggleButton
|
||||
className="toggle toggleButton"
|
||||
id="toggle id"
|
||||
isChecked={item.enabled}
|
||||
onChange={handleToggleEnabled}
|
||||
/>
|
||||
</ToggleButtonWrapper>
|
||||
</StyledRowContent>
|
||||
);
|
||||
};
|
@ -0,0 +1,67 @@
|
||||
import styled from "styled-components";
|
||||
|
||||
//@ts-ignore
|
||||
import RowContainer from "@docspace/components/row-container";
|
||||
//@ts-ignore
|
||||
import RowContent from "@docspace/components/row-content";
|
||||
|
||||
export const StyledRowContainer = styled(RowContainer)`
|
||||
margin-top: 0px;
|
||||
|
||||
.row-list-item {
|
||||
padding-left: 21px;
|
||||
}
|
||||
|
||||
.row-loader {
|
||||
width: calc(100% - 46px) !important;
|
||||
padding-left: 21px;
|
||||
}
|
||||
|
||||
img {
|
||||
width: 32px;
|
||||
max-width: 32px;
|
||||
|
||||
height: 32px;
|
||||
max-height: 32px;
|
||||
}
|
||||
`;
|
||||
|
||||
export const StyledRowContent = styled(RowContent)`
|
||||
display: flex;
|
||||
padding-bottom: 10px;
|
||||
|
||||
.rowMainContainer {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.mainIcons {
|
||||
min-width: 76px;
|
||||
}
|
||||
`;
|
||||
|
||||
export const ContentWrapper = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-items: center;
|
||||
`;
|
||||
|
||||
export const ToggleButtonWrapper = styled.div`
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
|
||||
label {
|
||||
margin-top: 1px;
|
||||
position: relative;
|
||||
gap: 0px;
|
||||
|
||||
margin-right: -8px;
|
||||
}
|
||||
`;
|
||||
|
||||
export const FlexWrapper = styled.div`
|
||||
display: flex;
|
||||
`;
|
@ -0,0 +1,49 @@
|
||||
import { ClientProps } from "@docspace/common/utils/oauth/interfaces";
|
||||
|
||||
//@ts-ignore
|
||||
import { ViewAsType } from "SRC_DIR/store/OAuthStore";
|
||||
|
||||
export interface RowViewProps {
|
||||
items: ClientProps[];
|
||||
sectionWidth: number;
|
||||
viewAs?: ViewAsType;
|
||||
setViewAs?: (value: ViewAsType) => void;
|
||||
selection?: string[];
|
||||
setSelection?: (clientId: string) => void;
|
||||
getContextMenuItems?: (
|
||||
t: any,
|
||||
item: ClientProps
|
||||
) => {
|
||||
[key: string]: any | string | boolean | ((clientId: string) => void);
|
||||
}[];
|
||||
activeClients?: string[];
|
||||
hasNextPage?: boolean;
|
||||
totalElements?: number;
|
||||
fetchNextClients?: (startIndex: number) => Promise<void>;
|
||||
changeClientStatus?: (clientId: string, status: boolean) => Promise<void>;
|
||||
}
|
||||
|
||||
export interface RowProps {
|
||||
item: ClientProps;
|
||||
isChecked: boolean;
|
||||
inProgress: boolean;
|
||||
sectionWidth: number;
|
||||
getContextMenuItems?: (
|
||||
t: any,
|
||||
item: ClientProps
|
||||
) => {
|
||||
[key: string]: any | string | boolean | ((clientId: string) => void);
|
||||
}[];
|
||||
setSelection?: (clientId: string) => void;
|
||||
changeClientStatus?: (clientId: string, status: boolean) => Promise<void>;
|
||||
}
|
||||
|
||||
export interface RowContentProps {
|
||||
sectionWidth: number;
|
||||
item: ClientProps;
|
||||
isChecked: boolean;
|
||||
inProgress: boolean;
|
||||
handleToggleEnabled: () => void;
|
||||
setSelection?: (clientId: string) => void;
|
||||
changeClientStatus?: (clientId: string, status: boolean) => Promise<void>;
|
||||
}
|
@ -0,0 +1,99 @@
|
||||
import React from "react";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { isMobile } from "react-device-detect";
|
||||
|
||||
//@ts-ignore
|
||||
import { OAuthStoreProps } from "SRC_DIR/store/OAuthStore";
|
||||
|
||||
import OAuthRow from "./Row";
|
||||
|
||||
import { RowViewProps } from "./RowView.types";
|
||||
import { StyledRowContainer } from "./RowView.styled";
|
||||
|
||||
const RowView = (props: RowViewProps) => {
|
||||
const {
|
||||
items,
|
||||
sectionWidth,
|
||||
viewAs,
|
||||
setViewAs,
|
||||
|
||||
changeClientStatus,
|
||||
selection,
|
||||
setSelection,
|
||||
|
||||
activeClients,
|
||||
getContextMenuItems,
|
||||
hasNextPage,
|
||||
totalElements,
|
||||
fetchNextClients,
|
||||
} = props;
|
||||
|
||||
React.useEffect(() => {
|
||||
if (viewAs !== "table" && viewAs !== "row") return;
|
||||
|
||||
if (sectionWidth < 1025 || isMobile) {
|
||||
viewAs !== "row" && setViewAs && setViewAs("row");
|
||||
} else {
|
||||
viewAs !== "table" && setViewAs && setViewAs("table");
|
||||
}
|
||||
}, [viewAs, setViewAs, sectionWidth]);
|
||||
|
||||
return (
|
||||
<StyledRowContainer
|
||||
itemHeight={59}
|
||||
filesLength={items.length}
|
||||
fetchMoreFiles={({
|
||||
startIndex,
|
||||
}: {
|
||||
startIndex: number;
|
||||
stopIndex: number;
|
||||
}) => fetchNextClients && fetchNextClients(startIndex)}
|
||||
hasMoreFiles={hasNextPage}
|
||||
itemCount={totalElements}
|
||||
useReactWindow={true}
|
||||
>
|
||||
{items.map((item) => (
|
||||
<OAuthRow
|
||||
key={item.clientId}
|
||||
item={item}
|
||||
isChecked={selection?.includes(item.clientId) || false}
|
||||
inProgress={activeClients?.includes(item.clientId) || false}
|
||||
setSelection={setSelection}
|
||||
changeClientStatus={changeClientStatus}
|
||||
getContextMenuItems={getContextMenuItems}
|
||||
sectionWidth={sectionWidth}
|
||||
/>
|
||||
))}
|
||||
</StyledRowContainer>
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(
|
||||
({ oauthStore }: { auth: any; oauthStore: OAuthStoreProps }) => {
|
||||
const {
|
||||
viewAs,
|
||||
setViewAs,
|
||||
selection,
|
||||
setSelection,
|
||||
changeClientStatus,
|
||||
getContextMenuItems,
|
||||
activeClients,
|
||||
hasNextPage,
|
||||
totalElements,
|
||||
fetchNextClients,
|
||||
} = oauthStore;
|
||||
|
||||
return {
|
||||
viewAs,
|
||||
setViewAs,
|
||||
changeClientStatus,
|
||||
selection,
|
||||
setSelection,
|
||||
activeClients,
|
||||
getContextMenuItems,
|
||||
hasNextPage,
|
||||
totalElements,
|
||||
fetchNextClients,
|
||||
};
|
||||
}
|
||||
)(observer(RowView));
|
@ -22,7 +22,7 @@ const Row = (props: RowProps) => {
|
||||
} = props;
|
||||
const navigate = useNavigate();
|
||||
|
||||
const { t } = useTranslation(["Webhooks", "Common"]);
|
||||
const { t } = useTranslation(["Common"]);
|
||||
|
||||
const editClient = () => {
|
||||
navigate(`${item.clientId}`);
|
||||
|
@ -11,6 +11,8 @@ import { Consumer } from "@docspace/components/utils/context";
|
||||
import { ViewAsType } from "SRC_DIR/store/OAuthStore";
|
||||
|
||||
import TableView from "./TableView";
|
||||
import RowView from "./RowView";
|
||||
|
||||
import RegisterNewButton from "../RegisterNewButton";
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
@ -82,7 +84,12 @@ const List = ({ t, clients, viewAs, setViewAs }: ListProps) => {
|
||||
sectionWidth={context.sectionWidth}
|
||||
/>
|
||||
) : (
|
||||
<div>row</div>
|
||||
<RowView
|
||||
viewAs={viewAs}
|
||||
setViewAs={setViewAs}
|
||||
items={clients || []}
|
||||
sectionWidth={context.sectionWidth}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
|
@ -37,6 +37,9 @@ export interface OAuthStoreProps {
|
||||
deleteDialogVisible: boolean;
|
||||
setDeleteDialogVisible: (value: boolean) => void;
|
||||
|
||||
clientsIsLoading: boolean;
|
||||
setClientsIsLoading: (value: boolean) => void;
|
||||
|
||||
editClient: (clientId: string) => void;
|
||||
|
||||
clients: ClientProps[];
|
||||
@ -85,7 +88,7 @@ export interface OAuthStoreProps {
|
||||
class OAuthStore implements OAuthStoreProps {
|
||||
viewAs: "table" | "row" = "table";
|
||||
|
||||
currentPage: number = 0;
|
||||
currentPage: number = -1;
|
||||
totalPages: number = 0;
|
||||
totalElements: number = 0;
|
||||
|
||||
@ -103,6 +106,8 @@ class OAuthStore implements OAuthStoreProps {
|
||||
|
||||
scopes: Scope[] = [];
|
||||
|
||||
clientsIsLoading: boolean = true;
|
||||
|
||||
constructor() {
|
||||
makeAutoObservable(this);
|
||||
}
|
||||
@ -135,6 +140,10 @@ class OAuthStore implements OAuthStoreProps {
|
||||
}
|
||||
};
|
||||
|
||||
setClientsIsLoading = (value: boolean) => {
|
||||
this.clientsIsLoading = value;
|
||||
};
|
||||
|
||||
setActiveClient = (clientId: string) => {
|
||||
if (!clientId) {
|
||||
this.activeClients = [];
|
||||
@ -175,10 +184,7 @@ class OAuthStore implements OAuthStoreProps {
|
||||
|
||||
fetchClients = async () => {
|
||||
try {
|
||||
runInAction(() => {
|
||||
this.currentPage = 1;
|
||||
});
|
||||
|
||||
this.setClientsIsLoading(true);
|
||||
const clientList: ClientListProps = await getClientList(0, PAGE_LIMIT);
|
||||
|
||||
runInAction(() => {
|
||||
@ -186,14 +192,23 @@ class OAuthStore implements OAuthStoreProps {
|
||||
|
||||
this.totalElements = clientList.totalElements;
|
||||
this.clients = clientList.content;
|
||||
this.selection = [];
|
||||
this.currentPage = 1;
|
||||
});
|
||||
this.setClientsIsLoading(false);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
};
|
||||
|
||||
fetchNextClients = async (startIndex: number) => {
|
||||
if (this.clientsIsLoading) return;
|
||||
this.setClientsIsLoading(true);
|
||||
|
||||
const page = startIndex / PAGE_LIMIT;
|
||||
|
||||
console.log(page);
|
||||
|
||||
runInAction(() => {
|
||||
this.currentPage = page + 1;
|
||||
});
|
||||
@ -205,6 +220,8 @@ class OAuthStore implements OAuthStoreProps {
|
||||
this.totalElements = clientList.totalElements;
|
||||
this.clients = [...this.clients, ...clientList.content];
|
||||
});
|
||||
|
||||
this.setClientsIsLoading(false);
|
||||
};
|
||||
|
||||
//TODO: OAuth, add tenant and other params
|
||||
@ -338,21 +355,21 @@ class OAuthStore implements OAuthStoreProps {
|
||||
const settingsOption = {
|
||||
key: "settings",
|
||||
icon: SettingsIcon,
|
||||
label: t("Common:Settings"),
|
||||
label: t("Settings"),
|
||||
onClick: () => this.editClient(clientId),
|
||||
};
|
||||
|
||||
const enableOption = {
|
||||
key: "enable",
|
||||
icon: EnableReactSvgUrl,
|
||||
label: t("Common:Enable"),
|
||||
label: t("Enable"),
|
||||
onClick: () => onEnable(true),
|
||||
};
|
||||
|
||||
const disableOption = {
|
||||
key: "disable",
|
||||
icon: RemoveReactSvgUrl,
|
||||
label: t("Common:Disable"),
|
||||
label: t("Disable"),
|
||||
onClick: () => onEnable(false),
|
||||
};
|
||||
|
||||
@ -363,7 +380,7 @@ class OAuthStore implements OAuthStoreProps {
|
||||
},
|
||||
{
|
||||
key: "delete",
|
||||
label: t("Common:Delete"),
|
||||
label: t("Delete"),
|
||||
icon: DeleteIcon,
|
||||
onClick: () => onDelete(),
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user