fix: update instances with full data
This commit is contained in:
@@ -47,6 +47,7 @@ const TableRow: React.FC<
|
|||||||
const childrenDataRef = useRef<any[]>([]);
|
const childrenDataRef = useRef<any[]>([]);
|
||||||
childrenDataRef.current = childrenData;
|
childrenDataRef.current = childrenData;
|
||||||
const axiosToken = useRef<any>(null);
|
const axiosToken = useRef<any>(null);
|
||||||
|
const [updateChild, setUpdateChild] = useState(true);
|
||||||
|
|
||||||
const { updateChunkedList, cacheDataListRef } = useUpdateChunkedList({
|
const { updateChunkedList, cacheDataListRef } = useUpdateChunkedList({
|
||||||
dataList: childrenData,
|
dataList: childrenData,
|
||||||
@@ -111,6 +112,9 @@ const TableRow: React.FC<
|
|||||||
};
|
};
|
||||||
|
|
||||||
const filterUpdateChildrenHandler = () => {
|
const filterUpdateChildrenHandler = () => {
|
||||||
|
if (!expanded) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const dataList = _.filter(tableContext.allChildren, (data: any) => {
|
const dataList = _.filter(tableContext.allChildren, (data: any) => {
|
||||||
return _.get(data, [childParentKey]) === _.get(record, [rowKey]);
|
return _.get(data, [childParentKey]) === _.get(record, [rowKey]);
|
||||||
});
|
});
|
||||||
@@ -161,6 +165,8 @@ const TableRow: React.FC<
|
|||||||
pollTimer.current = setInterval(() => {
|
pollTimer.current = setInterval(() => {
|
||||||
handlePolling();
|
handlePolling();
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
} else {
|
||||||
|
handleLoadChildren();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -186,17 +192,13 @@ const TableRow: React.FC<
|
|||||||
}
|
}
|
||||||
}, [expandedRowKeys]);
|
}, [expandedRowKeys]);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (expanded) {
|
|
||||||
handleLoadChildren();
|
|
||||||
}
|
|
||||||
}, [expanded]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleVisibilityChange = async () => {
|
const handleVisibilityChange = async () => {
|
||||||
if (document.visibilityState === 'hidden') {
|
if (document.visibilityState === 'hidden') {
|
||||||
cacheDataListRef.current = [];
|
cacheDataListRef.current = [];
|
||||||
// setChildrenData([]);
|
setUpdateChild(false);
|
||||||
|
} else {
|
||||||
|
setUpdateChild(true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -208,15 +210,15 @@ const TableRow: React.FC<
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!firstLoad && expanded) {
|
if (updateChild) {
|
||||||
cacheDataListRef.current = childrenData;
|
// for update watch data
|
||||||
filterUpdateChildrenHandler();
|
filterUpdateChildrenHandler();
|
||||||
}
|
}
|
||||||
return () => {
|
return () => {
|
||||||
chunkRequestRef.current?.current?.cancel?.();
|
chunkRequestRef.current?.current?.cancel?.();
|
||||||
cacheDataListRef.current = [];
|
cacheDataListRef.current = [];
|
||||||
};
|
};
|
||||||
}, [firstLoad, expanded, tableContext.allChildren]);
|
}, [updateChild, tableContext.allChildren]);
|
||||||
|
|
||||||
const renderRowPrefix = () => {
|
const renderRowPrefix = () => {
|
||||||
if (expandable && rowSelection) {
|
if (expandable && rowSelection) {
|
||||||
@@ -296,7 +298,8 @@ const TableRow: React.FC<
|
|||||||
renderChildrenData()
|
renderChildrenData()
|
||||||
) : (
|
) : (
|
||||||
<Empty
|
<Empty
|
||||||
image={Empty.PRESENTED_IMAGE_SIMPLE}
|
image={loading ? null : Empty.PRESENTED_IMAGE_SIMPLE}
|
||||||
|
description={loading ? null : undefined}
|
||||||
style={{
|
style={{
|
||||||
marginBlock: 0,
|
marginBlock: 0,
|
||||||
height: 54
|
height: 54
|
||||||
|
|||||||
@@ -0,0 +1,65 @@
|
|||||||
|
let bufferedData = '';
|
||||||
|
|
||||||
|
const findValidJSONStrings = (inputStr: string) => {
|
||||||
|
const validJSONStrings = [];
|
||||||
|
let startIndex = 0;
|
||||||
|
|
||||||
|
while (startIndex < inputStr.length) {
|
||||||
|
const openingBraceIndex = inputStr.indexOf('{', startIndex);
|
||||||
|
if (openingBraceIndex === -1) break; // No more opening braces
|
||||||
|
|
||||||
|
let closingBraceIndex = openingBraceIndex;
|
||||||
|
let braceCount = 0;
|
||||||
|
|
||||||
|
// find couple of braces
|
||||||
|
while (closingBraceIndex < inputStr.length) {
|
||||||
|
if (inputStr[closingBraceIndex] === '{') {
|
||||||
|
braceCount++;
|
||||||
|
} else if (inputStr[closingBraceIndex] === '}') {
|
||||||
|
braceCount--;
|
||||||
|
}
|
||||||
|
if (braceCount === 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
closingBraceIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (braceCount !== 0) {
|
||||||
|
// no matching closing brace
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const jsonString = inputStr.substring(
|
||||||
|
openingBraceIndex,
|
||||||
|
closingBraceIndex + 1
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const parsedData = JSON.parse(jsonString);
|
||||||
|
validJSONStrings.push(parsedData);
|
||||||
|
startIndex = closingBraceIndex + 1;
|
||||||
|
} catch (error) {
|
||||||
|
// mabye invalid JSON
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
parsedJSON: validJSONStrings,
|
||||||
|
remainingData: inputStr.slice(startIndex) // it is the not parsed data
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Web Worker
|
||||||
|
self.onmessage = function (event) {
|
||||||
|
bufferedData += event.data;
|
||||||
|
|
||||||
|
const { parsedJSON, remainingData } = findValidJSONStrings(bufferedData);
|
||||||
|
|
||||||
|
if (parsedJSON.length > 0) {
|
||||||
|
postMessage(parsedJSON);
|
||||||
|
}
|
||||||
|
|
||||||
|
// save the remaining data for the next message
|
||||||
|
bufferedData = remainingData;
|
||||||
|
};
|
||||||
@@ -36,69 +36,6 @@ export const sliceJsonStr = (text: string) => {
|
|||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const parseJsonStr = (list: string[]) => {
|
|
||||||
return _.map(list, (str: string) => {
|
|
||||||
return JSON.parse(str);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const findMatchingClosingBracket = (inputStr: string, startIndex: number) => {
|
|
||||||
let count = 0;
|
|
||||||
for (let i = startIndex; i < inputStr.length; i += 1) {
|
|
||||||
if (inputStr[i] === '{') {
|
|
||||||
count += 1;
|
|
||||||
} else if (inputStr[i] === '}') {
|
|
||||||
count -= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count === 0) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
};
|
|
||||||
|
|
||||||
const findValidJSONStrings = (inputStr: string) => {
|
|
||||||
const validJSONStrings: any[] = [];
|
|
||||||
let startIndex = 0;
|
|
||||||
|
|
||||||
while (startIndex < inputStr.length) {
|
|
||||||
const openingBraceIndex = inputStr.indexOf('{', startIndex);
|
|
||||||
if (openingBraceIndex === -1) {
|
|
||||||
break; // No more opening braces
|
|
||||||
}
|
|
||||||
|
|
||||||
const closingBraceIndex = findMatchingClosingBracket(
|
|
||||||
inputStr,
|
|
||||||
openingBraceIndex
|
|
||||||
);
|
|
||||||
if (closingBraceIndex === -1) {
|
|
||||||
// If no matching closing brace, set startIndex to next character
|
|
||||||
startIndex = openingBraceIndex + 1;
|
|
||||||
} else {
|
|
||||||
const jsonString = inputStr.substring(
|
|
||||||
openingBraceIndex,
|
|
||||||
closingBraceIndex + 1
|
|
||||||
);
|
|
||||||
try {
|
|
||||||
const data = JSON.parse(jsonString);
|
|
||||||
validJSONStrings.push(data);
|
|
||||||
} catch (error) {
|
|
||||||
// Ignore invalid JSON
|
|
||||||
}
|
|
||||||
|
|
||||||
startIndex = closingBraceIndex + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return validJSONStrings;
|
|
||||||
};
|
|
||||||
|
|
||||||
const parseData = (data: string) => {
|
|
||||||
const res = findValidJSONStrings(data);
|
|
||||||
return res;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const createAxiosToken = () => {
|
export const createAxiosToken = () => {
|
||||||
const { CancelToken } = axios;
|
const { CancelToken } = axios;
|
||||||
const source = CancelToken.source();
|
const source = CancelToken.source();
|
||||||
@@ -123,7 +60,7 @@ const useSetChunkRequest = () => {
|
|||||||
const particalConfig = { params: {}, contentType: 'json' };
|
const particalConfig = { params: {}, contentType: 'json' };
|
||||||
const timer = useRef<any>(null);
|
const timer = useRef<any>(null);
|
||||||
const loadedSize = useRef(0);
|
const loadedSize = useRef(0);
|
||||||
const bufferedDataRef = useRef('');
|
const workerRef = useRef<any>(null);
|
||||||
|
|
||||||
const reset = () => {
|
const reset = () => {
|
||||||
loaded.current = 0;
|
loaded.current = 0;
|
||||||
@@ -172,6 +109,23 @@ const useSetChunkRequest = () => {
|
|||||||
cancelWatchRequest(watchRequestList.length - 4 || 1);
|
cancelWatchRequest(watchRequestList.length - 4 || 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (contentType === 'json') {
|
||||||
|
workerRef.current?.terminate();
|
||||||
|
|
||||||
|
workerRef.current = new Worker(
|
||||||
|
// @ts-ignore
|
||||||
|
new URL('./json-parser-worker.ts', import.meta.url)
|
||||||
|
);
|
||||||
|
|
||||||
|
workerRef.current.onmessage = function (event: any) {
|
||||||
|
const validJSON = event.data;
|
||||||
|
if (validJSON.length > 0) {
|
||||||
|
const result = resetResultSchema(validJSON);
|
||||||
|
handler(result);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const { request: requestData } = await request(url, {
|
const { request: requestData } = await request(url, {
|
||||||
params: {
|
params: {
|
||||||
@@ -188,38 +142,17 @@ const useSetChunkRequest = () => {
|
|||||||
loaded.current = e.loaded || 0;
|
loaded.current = e.loaded || 0;
|
||||||
total.current = e.total || 0;
|
total.current = e.total || 0;
|
||||||
|
|
||||||
let currentRes = sliceData(response, e.loaded, loadedSize);
|
|
||||||
let result: any[] = [];
|
|
||||||
let cres = currentRes;
|
|
||||||
|
|
||||||
if (contentType === 'json') {
|
if (contentType === 'json') {
|
||||||
// Append the new data to the buffered data
|
let currentRes = sliceData(response, e.loaded, loadedSize);
|
||||||
bufferedDataRef.current += currentRes;
|
workerRef.current.postMessage(currentRes);
|
||||||
|
|
||||||
// Find valid JSON strings in the buffered data
|
|
||||||
let validJSON = findValidJSONStrings(bufferedDataRef.current);
|
|
||||||
if (validJSON.length > 0) {
|
|
||||||
result = resetResultSchema(validJSON);
|
|
||||||
|
|
||||||
// Calculate the position of the last complete JSON fragment, keeping the unfinished part
|
|
||||||
const lastValidJSON = validJSON[validJSON.length - 1];
|
|
||||||
const lastJSONIndex = bufferedDataRef.current.lastIndexOf(
|
|
||||||
JSON.stringify(lastValidJSON)
|
|
||||||
);
|
|
||||||
bufferedDataRef.current = bufferedDataRef.current.slice(
|
|
||||||
lastJSONIndex + JSON.stringify(lastValidJSON).length
|
|
||||||
);
|
|
||||||
}
|
|
||||||
handler(result);
|
|
||||||
} else {
|
} else {
|
||||||
handler(currentRes);
|
handler(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('chunkrequest===', {
|
console.log('chunkrequest===', {
|
||||||
result,
|
result: response,
|
||||||
url,
|
url,
|
||||||
params,
|
params
|
||||||
raw: cres
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -9,7 +9,12 @@ import {
|
|||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import qs from 'query-string';
|
import qs from 'query-string';
|
||||||
import { memo, useCallback, useEffect, useRef, useState } from 'react';
|
import { memo, useCallback, useEffect, useRef, useState } from 'react';
|
||||||
import { MODELS_API, MODEL_INSTANCE_API, queryModelsList } from './apis';
|
import {
|
||||||
|
MODELS_API,
|
||||||
|
MODEL_INSTANCE_API,
|
||||||
|
queryModelsInstances,
|
||||||
|
queryModelsList
|
||||||
|
} from './apis';
|
||||||
import TableList from './components/table-list';
|
import TableList from './components/table-list';
|
||||||
import { ListItem } from './config/types';
|
import { ListItem } from './config/types';
|
||||||
|
|
||||||
@@ -81,39 +86,60 @@ const Models: React.FC = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetchData = useCallback(async () => {
|
const getAllModelInstances = useCallback(async () => {
|
||||||
axiosToken?.cancel?.();
|
|
||||||
axiosToken = createAxiosToken();
|
|
||||||
setDataSource((pre) => {
|
|
||||||
pre.loading = true;
|
|
||||||
return { ...pre };
|
|
||||||
});
|
|
||||||
try {
|
try {
|
||||||
|
instancesToken.current?.cancel?.();
|
||||||
|
instancesToken.current = createAxiosToken();
|
||||||
const params = {
|
const params = {
|
||||||
..._.pickBy(queryParams, (val: any) => !!val)
|
page: 1,
|
||||||
|
perPage: 100
|
||||||
};
|
};
|
||||||
const res: any = await queryModelsList(params, {
|
const res: any = await queryModelsInstances(params, {
|
||||||
cancelToken: axiosToken.token
|
token: instancesToken.current.token
|
||||||
});
|
|
||||||
setDataSource({
|
|
||||||
dataList: res.items || [],
|
|
||||||
loading: false,
|
|
||||||
loadend: true,
|
|
||||||
total: res.pagination.total,
|
|
||||||
deletedIds: []
|
|
||||||
});
|
});
|
||||||
|
cacheInsDataListRef.current = res.items || [];
|
||||||
|
setModelInstances(res.items || []);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (!isPageHidden.current) {
|
// ignore
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const fetchData = useCallback(
|
||||||
|
async (loadingVal?: boolean) => {
|
||||||
|
axiosToken?.cancel?.();
|
||||||
|
axiosToken = createAxiosToken();
|
||||||
|
setDataSource((pre) => {
|
||||||
|
pre.loading = loadingVal ?? true;
|
||||||
|
return { ...pre };
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
const params = {
|
||||||
|
..._.pickBy(queryParams, (val: any) => !!val)
|
||||||
|
};
|
||||||
|
const res: any = await queryModelsList(params, {
|
||||||
|
cancelToken: axiosToken.token
|
||||||
|
});
|
||||||
setDataSource({
|
setDataSource({
|
||||||
dataList: [],
|
dataList: res.items || [],
|
||||||
loading: false,
|
loading: false,
|
||||||
loadend: true,
|
loadend: true,
|
||||||
total: dataSource.total,
|
total: res.pagination.total,
|
||||||
deletedIds: []
|
deletedIds: []
|
||||||
});
|
});
|
||||||
|
} catch (error) {
|
||||||
|
if (!isPageHidden.current) {
|
||||||
|
setDataSource({
|
||||||
|
dataList: [],
|
||||||
|
loading: false,
|
||||||
|
loadend: true,
|
||||||
|
total: dataSource.total,
|
||||||
|
deletedIds: []
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}, [queryParams]);
|
[queryParams]
|
||||||
|
);
|
||||||
|
|
||||||
const handlePageChange = useCallback(
|
const handlePageChange = useCallback(
|
||||||
(page: number, pageSize: number | undefined) => {
|
(page: number, pageSize: number | undefined) => {
|
||||||
@@ -135,6 +161,7 @@ const Models: React.FC = () => {
|
|||||||
const updateInstanceHandler = (list: any) => {
|
const updateInstanceHandler = (list: any) => {
|
||||||
// filter the data
|
// filter the data
|
||||||
_.each(list, (data: any) => {
|
_.each(list, (data: any) => {
|
||||||
|
console.log('updateInstanceHandler====', data);
|
||||||
updateInstanceChunkedList(data);
|
updateInstanceChunkedList(data);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -166,7 +193,7 @@ const Models: React.FC = () => {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
}, []);
|
}, [updateInstanceHandler]);
|
||||||
|
|
||||||
const handleOnViewLogs = useCallback(() => {
|
const handleOnViewLogs = useCallback(() => {
|
||||||
isPageHidden.current = true;
|
isPageHidden.current = true;
|
||||||
@@ -174,13 +201,15 @@ const Models: React.FC = () => {
|
|||||||
cacheDataListRef.current = [];
|
cacheDataListRef.current = [];
|
||||||
cacheInsDataListRef.current = [];
|
cacheInsDataListRef.current = [];
|
||||||
chunkInstanceRequedtRef.current?.current?.cancel?.();
|
chunkInstanceRequedtRef.current?.current?.cancel?.();
|
||||||
|
instancesToken.current?.cancel?.();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleOnCancelViewLogs = useCallback(async () => {
|
const handleOnCancelViewLogs = useCallback(async () => {
|
||||||
isPageHidden.current = false;
|
isPageHidden.current = false;
|
||||||
|
await getAllModelInstances();
|
||||||
await createModelsInstanceChunkRequest();
|
await createModelsInstanceChunkRequest();
|
||||||
await createModelsChunkRequest();
|
await createModelsChunkRequest();
|
||||||
fetchData();
|
fetchData(false);
|
||||||
}, [fetchData, createModelsChunkRequest, createModelsInstanceChunkRequest]);
|
}, [fetchData, createModelsChunkRequest, createModelsInstanceChunkRequest]);
|
||||||
|
|
||||||
const handleSearch = useCallback(async () => {
|
const handleSearch = useCallback(async () => {
|
||||||
@@ -232,19 +261,25 @@ const Models: React.FC = () => {
|
|||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
console.log('modelInstances====', modelInstances);
|
||||||
|
}, [modelInstances]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleVisibilityChange = async () => {
|
const handleVisibilityChange = async () => {
|
||||||
if (document.visibilityState === 'visible') {
|
if (document.visibilityState === 'visible') {
|
||||||
isPageHidden.current = false;
|
isPageHidden.current = false;
|
||||||
|
await getAllModelInstances();
|
||||||
await createModelsInstanceChunkRequest();
|
await createModelsInstanceChunkRequest();
|
||||||
await createModelsChunkRequest();
|
await createModelsChunkRequest();
|
||||||
fetchData();
|
fetchData(false);
|
||||||
} else {
|
} else {
|
||||||
isPageHidden.current = true;
|
isPageHidden.current = true;
|
||||||
chunkRequedtRef.current?.current?.cancel?.();
|
chunkRequedtRef.current?.current?.cancel?.();
|
||||||
cacheDataListRef.current = [];
|
cacheDataListRef.current = [];
|
||||||
cacheInsDataListRef.current = [];
|
cacheInsDataListRef.current = [];
|
||||||
chunkInstanceRequedtRef.current?.current?.cancel?.();
|
chunkInstanceRequedtRef.current?.current?.cancel?.();
|
||||||
|
instancesToken.current?.cancel?.();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user