Skip to content

Commit

Permalink
feat(web): add resize layout & function page prompt (#856)
Browse files Browse the repository at this point in the history
  • Loading branch information
kongwy229 authored Mar 6, 2023
1 parent 92e570f commit d1fb07c
Show file tree
Hide file tree
Showing 21 changed files with 395 additions and 55 deletions.
2 changes: 1 addition & 1 deletion web/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,4 @@
"prettier --write"
]
}
}
}
3 changes: 2 additions & 1 deletion web/public/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,8 @@
"FunctionNameRule": "Function names can only contain English or _",
"EmptyDebugTip": "No results yet",
"EmptyFunctionTip": "You have not created the function",
"UploadButton": "upload"
"UploadButton": "upload",
"LeaveFunctionPage": "About to leave the function edit page"
},
"HomePanel": {
"APP": "Android or iOS app",
Expand Down
3 changes: 2 additions & 1 deletion web/public/locales/zh-CN/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,8 @@
"FunctionNameRule": "函数名只能包含英文或 _",
"EmptyDebugTip": "暂无运行结果",
"EmptyFunctionTip": "您还没有创建函数",
"UploadButton": "上传"
"UploadButton": "上传",
"LeaveFunctionPage": "即将离开函数编辑页面"
},
"HomePanel": {
"APP": "Android or iOS 应用",
Expand Down
3 changes: 2 additions & 1 deletion web/public/locales/zh/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,8 @@
"FunctionNameRule": "函数名只能包含英文或 _",
"EmptyDebugTip": "暂无运行结果",
"EmptyFunctionTip": "您还没有创建函数",
"UploadButton": "上传"
"UploadButton": "上传",
"LeaveFunctionPage": "即将离开函数编辑页面"
},
"HomePanel": {
"APP": "Android or iOS 应用",
Expand Down
48 changes: 27 additions & 21 deletions web/src/components/Grid/index.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,35 @@
import React from "react";
import { forwardRef } from "react";
import clsx from "clsx";

function Grid() {
return <div>Grid</div>;
}

function Row(props: {
className?: string;
style?: React.CSSProperties;
children: React.ReactNode;
}) {
const { className, style } = props;
return (
<div
className={clsx(
"flex space-x-2 w-full",
style?.height ? "flex-none" : "flex-grow",
className,
)}
style={style}
>
{props.children}
</div>
);
}
const Row = forwardRef(
(
props: {
className?: string;
style?: React.CSSProperties;
children: React.ReactNode;
},
ref: any,
) => {
const { className, style } = props;
return (
<div
ref={ref}
className={clsx(
"flex w-full overflow-hidden",
style?.height ? "flex-none" : "flex-grow",
className,
)}
style={style}
>
{props.children}
</div>
);
},
);

function Col(props: {
className?: string;
Expand All @@ -34,7 +40,7 @@ function Col(props: {
return (
<div
className={clsx(
"flex flex-col space-y-2 h-full",
"flex flex-col h-full overflow-x-hidden",
style?.width ? "flex-none" : "flex-grow flex-1 overflow-hidden",
className,
)}
Expand Down
72 changes: 72 additions & 0 deletions web/src/components/Resize/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { useEffect } from "react";
import { ChevronLeftIcon, ChevronRightIcon } from "@chakra-ui/icons";
import { Center } from "@chakra-ui/react";
import clsx from "clsx";

import useResizable from "@/hooks/useResizable";
import { page, panel } from "@/pages/customSetting";
import useCustomSettingStore from "@/pages/customSetting";
export default function Resize(props: {
type: "x" | "y";
reverse?: boolean;
pageId: page;
panelId: panel;
containerRef: any;
}) {
const { type, pageId, panelId, reverse, containerRef } = props;
const store = useCustomSettingStore();
const { width, height, minWidth, maxWidth, minHeight, maxHeight, display } = store.getLayoutInfo(
pageId,
panelId,
);
const { isDragging, position, separatorProps } = useResizable({
axis: type,
initial: type === "x" ? width : height,
min: type === "x" ? minWidth : minHeight,
max: type === "x" ? maxWidth : maxHeight,
reverse,
containerRef,
});
useEffect(() => {
const newPosition = {
width: position,
height: position,
};
store.setLayoutInfo(pageId, panelId, newPosition);
}, [position, pageId, panelId, store]);

return (
<>
{display === "none" ? null : (
<div
className={
type === "x" ? "h-full w-2 cursor-col-resize group" : "h-2 w-full cursor-row-resize"
}
{...separatorProps}
>
<Center className="w-full h-full">
{type === "x" && width <= 20 ? (
<div
className={clsx(
reverse ? "rounded-l-lg" : "rounded-r-lg",
"w-2 h-[30px] bg-grayIron-300 group-hover:bg-grayIron-400 transition-colors leading-loose text-lafWhite-600",
)}
>
{reverse ? <ChevronLeftIcon fontSize={10} /> : <ChevronRightIcon fontSize={10} />}
</div>
) : (
<div
className={clsx(
type === "x" && isDragging ? "h-full " : "h-0",
type === "y" && isDragging ? "w-full " : "w-0",
isDragging ? " border-primary-400 " : "",
"border-l-2 border-t-2 transition-all",
)}
></div>
)}
</Center>
</div>
)}
</>
);
}
118 changes: 118 additions & 0 deletions web/src/hooks/useResizable.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import type React from "react";
import { useCallback, useMemo, useRef, useState } from "react";

type SeparatorProps = React.ComponentPropsWithoutRef<"hr">;
type Resizable = {
position: number;
isDragging: boolean;
separatorProps: SeparatorProps;
};
type UseResizableProps = {
axis: "x" | "y";
containerRef?: React.RefObject<HTMLElement>;
disabled?: boolean;
initial?: number;
min?: number;
max?: number;
reverse?: boolean;
};

export type ResizableProps = UseResizableProps & {
children: (props: Resizable) => JSX.Element;
};

const useResizable = ({
axis,
disabled = false,
initial = 0,
min = 0,
max = Infinity,
reverse,
containerRef,
}: UseResizableProps): Resizable => {
const isResizing = useRef(false);
const [isDragging, setIsDragging] = useState(false);
const [position, setPosition] = useState(Math.min(Math.max(initial, min), max));

const ariaProps = useMemo<SeparatorProps>(
() => ({
role: "separator",
"aria-valuenow": position,
"aria-valuemin": min,
"aria-valuemax": max,
"aria-orientation": axis === "x" ? "vertical" : "horizontal",
"aria-disabled": disabled,
}),
[axis, disabled, max, min, position],
);

const handleMove = useCallback(
(e: MouseEvent | TouchEvent) => {
if (!isResizing.current) return;
if (disabled) return;
e.stopPropagation();
e.preventDefault();
const currentPosition = (() => {
if (axis === "x") {
const x = e instanceof MouseEvent ? e.clientX : e.touches[0].clientX;
if (containerRef?.current) {
const containerNode = containerRef.current;
const { left, width } = containerNode.getBoundingClientRect();
return reverse ? left + width - x : x - left;
}
return reverse ? document.body.offsetWidth - x : x;
}
const y = e instanceof MouseEvent ? e.clientY : e.touches[0].clientY;
if (containerRef?.current) {
const containerNode = containerRef.current;
const { top, height } = containerNode.getBoundingClientRect();
return reverse ? top + height - y : y - top;
}
return reverse ? document.body.offsetHeight - y : y;
})();
if (min < currentPosition && currentPosition < max) {
setPosition(currentPosition);
}
},
[axis, disabled, max, min, reverse, containerRef],
);

const handleUp = useCallback(
(e: MouseEvent | TouchEvent) => {
if (disabled) return;
e.stopPropagation();
isResizing.current = false;
setIsDragging(false);
document.removeEventListener("mousemove", handleMove);
document.removeEventListener("touchmove", handleMove);
document.removeEventListener("mouseup", handleUp);
document.removeEventListener("touchend", handleUp);
},
[disabled, handleMove],
);

const handleDown = useCallback<any>(
(e: React.MouseEvent | React.TouchEvent) => {
if (disabled) return;
e.stopPropagation();
isResizing.current = true;
setIsDragging(true);
document.addEventListener("mousemove", handleMove);
document.addEventListener("touchmove", handleMove);
document.addEventListener("mouseup", handleUp);
document.addEventListener("touchend", handleUp);
},
[disabled, handleMove, handleUp],
);
return {
position,
isDragging,
separatorProps: {
...ariaProps,
onMouseDown: handleDown,
onTouchStart: handleDown,
},
};
};

export default useResizable;
2 changes: 1 addition & 1 deletion web/src/pages/app/database/CollectionListPanel/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export default function CollectionListPanel() {

return (
<Panel
className="flex-grow overflow-hidden"
className="flex-grow overflow-hidden min-w-[200px]"
onClick={() => {
store.setCurrentShow("DB");
}}
Expand Down
1 change: 1 addition & 0 deletions web/src/pages/app/database/PolicyListPanel/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export default function PolicyListPanel() {
});
return (
<Panel
className="min-w-[200px]"
onClick={() => {
store.setCurrentShow("Policy");
}}
Expand Down
14 changes: 13 additions & 1 deletion web/src/pages/app/database/index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
/****************************
* cloud functions database page
***************************/
import { useRef } from "react";

import Content from "@/components/Content";
import { Col, Row } from "@/components/Grid";
import Panel from "@/components/Panel";
import Resize from "@/components/Resize";

import BottomPanel from "./BottomPanel";
import CollectionDataList from "./CollectionDataList";
Expand All @@ -15,17 +18,26 @@ import useDBMStore from "./store";

import useCustomSettingStore from "@/pages/customSetting";
function DatabasePage() {
const containerRef = useRef<HTMLDivElement>(null);
const store = useDBMStore((state) => state);
const settingStore = useCustomSettingStore();
return (
<Content>
<Row className="flex-grow overflow-hidden">
<Row className="flex-grow" ref={containerRef}>
<Col {...settingStore.layoutInfo.collectionPage.SideBar}>
<CollectionListPanel />
<Resize
type="y"
pageId="collectionPage"
panelId="PolicyPanel"
reverse
containerRef={containerRef}
/>
<Row {...settingStore.layoutInfo.collectionPage.PolicyPanel}>
<PolicyListPanel />
</Row>
</Col>
<Resize type="x" pageId="collectionPage" panelId="SideBar" containerRef={containerRef} />
<Col>
<Panel className="items-center h-full">
{store.currentShow === "DB" ? <CollectionDataList /> : <PolicyDataList />}
Expand Down
Loading

0 comments on commit d1fb07c

Please sign in to comment.