fix: logs viewer do not scroll after opened
This commit is contained in:
@@ -3,7 +3,7 @@ import { IApi } from '@umijs/max';
|
|||||||
export default (api: IApi) => {
|
export default (api: IApi) => {
|
||||||
api.modifyHTML(($) => {
|
api.modifyHTML(($) => {
|
||||||
const info = JSON.parse(process.env.VERSION || '{}');
|
const info = JSON.parse(process.env.VERSION || '{}');
|
||||||
const env = info.version ? 'production' : 'development';
|
const env = process.env.NODE_ENV;
|
||||||
|
|
||||||
$('html').attr('data-env', env);
|
$('html').attr('data-env', env);
|
||||||
|
|
||||||
|
|||||||
@@ -15,10 +15,16 @@ interface LogsViewerProps {
|
|||||||
}
|
}
|
||||||
const LogsViewer: React.FC<LogsViewerProps> = (props) => {
|
const LogsViewer: React.FC<LogsViewerProps> = (props) => {
|
||||||
const { height, url } = props;
|
const { height, url } = props;
|
||||||
const { initialize, updateScrollerPosition, scrollEventElement } =
|
const {
|
||||||
useOverlayScroller({
|
initialize,
|
||||||
theme: 'os-theme-light'
|
updateScrollerPosition,
|
||||||
});
|
generateInstance,
|
||||||
|
scrollEventElement,
|
||||||
|
instance,
|
||||||
|
initialized
|
||||||
|
} = useOverlayScroller({
|
||||||
|
theme: 'os-theme-light'
|
||||||
|
});
|
||||||
const { isClean, parseAnsi } = useParseAnsi();
|
const { isClean, parseAnsi } = useParseAnsi();
|
||||||
const { setChunkFetch } = useSetChunkFetch();
|
const { setChunkFetch } = useSetChunkFetch();
|
||||||
const chunkRequedtRef = useRef<any>(null);
|
const chunkRequedtRef = useRef<any>(null);
|
||||||
@@ -62,11 +68,12 @@ const LogsViewer: React.FC<LogsViewerProps> = (props) => {
|
|||||||
const debounceResetStopScroll = _.debounce(() => {
|
const debounceResetStopScroll = _.debounce(() => {
|
||||||
stopScroll.current = false;
|
stopScroll.current = false;
|
||||||
}, 30000);
|
}, 30000);
|
||||||
|
|
||||||
const handleOnWheel = useCallback(
|
const handleOnWheel = useCallback(
|
||||||
(e: any) => {
|
(e: any) => {
|
||||||
const scrollTop = scrollEventElement.scrollTop;
|
const scrollTop = scrollEventElement?.scrollTop;
|
||||||
const scrollHeight = scrollEventElement.scrollHeight;
|
const scrollHeight = scrollEventElement?.scrollHeight;
|
||||||
const clientHeight = scrollEventElement.clientHeight;
|
const clientHeight = scrollEventElement?.clientHeight;
|
||||||
if (scrollTop + clientHeight >= scrollHeight) {
|
if (scrollTop + clientHeight >= scrollHeight) {
|
||||||
stopScroll.current = false;
|
stopScroll.current = false;
|
||||||
} else {
|
} else {
|
||||||
@@ -74,9 +81,14 @@ const LogsViewer: React.FC<LogsViewerProps> = (props) => {
|
|||||||
}
|
}
|
||||||
debounceResetStopScroll();
|
debounceResetStopScroll();
|
||||||
},
|
},
|
||||||
[debounceResetStopScroll]
|
[debounceResetStopScroll, scrollEventElement]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const debounceUpdateScrollerPosition = _.debounce(() => {
|
||||||
|
generateInstance();
|
||||||
|
updateScrollerPosition(0);
|
||||||
|
}, 200);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
createChunkConnection();
|
createChunkConnection();
|
||||||
return () => {
|
return () => {
|
||||||
@@ -91,10 +103,19 @@ const LogsViewer: React.FC<LogsViewerProps> = (props) => {
|
|||||||
}, [scroller.current, initialize]);
|
}, [scroller.current, initialize]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (logs.length && !stopScroll.current) {
|
if (logs.length && !stopScroll.current && instance) {
|
||||||
updateScrollerPosition(0);
|
updateScrollerPosition(0);
|
||||||
|
} else if (logs.length && !stopScroll.current && scroller.current) {
|
||||||
|
if (!initialized) {
|
||||||
|
initialize(scroller.current);
|
||||||
|
}
|
||||||
|
if (!instance) {
|
||||||
|
debounceUpdateScrollerPosition();
|
||||||
|
} else {
|
||||||
|
updateScrollerPosition(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, [logs, stopScroll.current]);
|
}, [logs, stopScroll.current, instance, scroller.current]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="logs-viewer-wrap-w2">
|
<div className="logs-viewer-wrap-w2">
|
||||||
|
|||||||
@@ -10,8 +10,7 @@ const VersionInfo: React.FC<{ intl: any }> = ({ intl }) => {
|
|||||||
const latestVersion = getAtomStorage(UpdateCheckAtom).latest_version;
|
const latestVersion = getAtomStorage(UpdateCheckAtom).latest_version;
|
||||||
const currentVersion = getAtomStorage(GPUStackVersionAtom)?.version;
|
const currentVersion = getAtomStorage(GPUStackVersionAtom)?.version;
|
||||||
|
|
||||||
const isProd =
|
const isProd = currentVersion !== '0.0.0';
|
||||||
document.documentElement.getAttribute('data-env') === 'production';
|
|
||||||
|
|
||||||
const uiVersion = document.documentElement.getAttribute('data-version');
|
const uiVersion = document.documentElement.getAttribute('data-version');
|
||||||
|
|
||||||
@@ -51,7 +50,9 @@ const VersionInfo: React.FC<{ intl: any }> = ({ intl }) => {
|
|||||||
{getAtomStorage(userAtom)?.is_admin && (
|
{getAtomStorage(userAtom)?.is_admin && (
|
||||||
<div className="upgrade">
|
<div className="upgrade">
|
||||||
<span className="m-l-5">
|
<span className="m-l-5">
|
||||||
{latestVersion && latestVersion !== currentVersion
|
{latestVersion &&
|
||||||
|
latestVersion !== currentVersion &&
|
||||||
|
latestVersion !== '0.0.0'
|
||||||
? intl.formatMessage(
|
? intl.formatMessage(
|
||||||
{ id: 'users.version.update' },
|
{ id: 'users.version.update' },
|
||||||
{ version: latestVersion }
|
{ version: latestVersion }
|
||||||
|
|||||||
@@ -509,6 +509,28 @@ body {
|
|||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ant-modal-centered.ant-modal-wrap {
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
width: var(--scrollbar-size);
|
||||||
|
}
|
||||||
|
|
||||||
|
&::-webkit-scrollbar-thumb {
|
||||||
|
background-color: transparent;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::-webkit-scrollbar-track {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
&::-webkit-scrollbar-thumb {
|
||||||
|
background-color: var(--scrollbar-handle-bg);
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.custome-scrollbar {
|
.custome-scrollbar {
|
||||||
&::-webkit-scrollbar {
|
&::-webkit-scrollbar {
|
||||||
width: var(--scrollbar-size);
|
width: var(--scrollbar-size);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { throttle } from 'lodash';
|
import { throttle } from 'lodash';
|
||||||
import {
|
import {
|
||||||
useOverlayScrollbars,
|
UseOverlayScrollbarsParams,
|
||||||
UseOverlayScrollbarsParams
|
useOverlayScrollbars
|
||||||
} from 'overlayscrollbars-react';
|
} from 'overlayscrollbars-react';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
@@ -26,6 +26,7 @@ export const overlaySollerOptions: UseOverlayScrollbarsParams = {
|
|||||||
export default function useOverlayScroller(options?: any) {
|
export default function useOverlayScroller(options?: any) {
|
||||||
const scrollEventElement = React.useRef<any>(null);
|
const scrollEventElement = React.useRef<any>(null);
|
||||||
const instanceRef = React.useRef<any>(null);
|
const instanceRef = React.useRef<any>(null);
|
||||||
|
const initialized = React.useRef(false);
|
||||||
const [initialize, instance] = useOverlayScrollbars({
|
const [initialize, instance] = useOverlayScrollbars({
|
||||||
options: {
|
options: {
|
||||||
update: {
|
update: {
|
||||||
@@ -43,6 +44,7 @@ export default function useOverlayScroller(options?: any) {
|
|||||||
},
|
},
|
||||||
defer: true
|
defer: true
|
||||||
});
|
});
|
||||||
|
|
||||||
instanceRef.current = instance?.();
|
instanceRef.current = instance?.();
|
||||||
scrollEventElement.current =
|
scrollEventElement.current =
|
||||||
instanceRef.current?.elements()?.scrollEventElement;
|
instanceRef.current?.elements()?.scrollEventElement;
|
||||||
@@ -78,6 +80,12 @@ export default function useOverlayScroller(options?: any) {
|
|||||||
[throttledScroll, scrollauto]
|
[throttledScroll, scrollauto]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const generateInstance = () => {
|
||||||
|
instanceRef.current = instance?.();
|
||||||
|
scrollEventElement.current =
|
||||||
|
instanceRef.current?.elements()?.scrollEventElement;
|
||||||
|
};
|
||||||
|
|
||||||
const createInstance = React.useCallback(
|
const createInstance = React.useCallback(
|
||||||
(el: any) => {
|
(el: any) => {
|
||||||
if (instanceRef.current) {
|
if (instanceRef.current) {
|
||||||
@@ -85,6 +93,14 @@ export default function useOverlayScroller(options?: any) {
|
|||||||
}
|
}
|
||||||
if (el) {
|
if (el) {
|
||||||
initialize(el);
|
initialize(el);
|
||||||
|
initialized.current = true;
|
||||||
|
console.log(
|
||||||
|
'createInstance===2',
|
||||||
|
initialized.current,
|
||||||
|
instanceRef.current,
|
||||||
|
instance?.(),
|
||||||
|
instance
|
||||||
|
);
|
||||||
instanceRef.current = instance?.();
|
instanceRef.current = instance?.();
|
||||||
scrollEventElement.current =
|
scrollEventElement.current =
|
||||||
instanceRef.current?.elements()?.scrollEventElement;
|
instanceRef.current?.elements()?.scrollEventElement;
|
||||||
@@ -97,6 +113,8 @@ export default function useOverlayScroller(options?: any) {
|
|||||||
initialize: createInstance,
|
initialize: createInstance,
|
||||||
instance: instanceRef.current,
|
instance: instanceRef.current,
|
||||||
scrollEventElement: scrollEventElement.current,
|
scrollEventElement: scrollEventElement.current,
|
||||||
|
initialized: initialized.current,
|
||||||
|
generateInstance,
|
||||||
updateScrollerPosition: throttledUpdateScrollerPosition
|
updateScrollerPosition: throttledUpdateScrollerPosition
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,6 @@ export default {
|
|||||||
'users.password.confirm.empty': 'Please confirm the new password.',
|
'users.password.confirm.empty': 'Please confirm the new password.',
|
||||||
'users.password.confirm.error': 'The two passwords entered do not match.',
|
'users.password.confirm.error': 'The two passwords entered do not match.',
|
||||||
'users.login.title': 'Log in to {name}',
|
'users.login.title': 'Log in to {name}',
|
||||||
'users.version.islatest': '{version} is the latest version',
|
'users.version.islatest': 'GPUStack {version} is the latest version',
|
||||||
'users.version.update': 'GPUStack {version} is available'
|
'users.version.update': 'GPUStack {version} is available'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -25,6 +25,6 @@ export default {
|
|||||||
'users.password.confirm.empty': '请确认新密码',
|
'users.password.confirm.empty': '请确认新密码',
|
||||||
'users.password.confirm.error': '两次输入的密码不一致',
|
'users.password.confirm.error': '两次输入的密码不一致',
|
||||||
'users.login.title': '登录 {name}',
|
'users.login.title': '登录 {name}',
|
||||||
'users.version.islatest': '{version} 已是最新版本',
|
'users.version.islatest': 'GPUStack {version} 已是最新版本',
|
||||||
'users.version.update': 'GPUStack {version} 版本可供更新'
|
'users.version.update': 'GPUStack {version} 版本可供更新'
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user