mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2024-11-22 08:46:39 -06:00
Fixed issues found in testing of react-table upgrade changes. #7419
UI fixes and improvement in System Stats Dashboard.
This commit is contained in:
parent
9647482791
commit
d6a9f8a06c
@ -21,6 +21,7 @@ import {useInterval, usePrevious} from 'sources/custom_hooks';
|
|||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { getStatsUrl, transformData, statsReducer, X_AXIS_LENGTH } from './utility.js';
|
import { getStatsUrl, transformData, statsReducer, X_AXIS_LENGTH } from './utility.js';
|
||||||
import { toPrettySize } from '../../../../static/js/utils';
|
import { toPrettySize } from '../../../../static/js/utils';
|
||||||
|
import SectionContainer from '../components/SectionContainer.jsx';
|
||||||
|
|
||||||
const useStyles = makeStyles((theme) => ({
|
const useStyles = makeStyles((theme) => ({
|
||||||
autoResizer: {
|
autoResizer: {
|
||||||
@ -252,7 +253,7 @@ export function CPUWrapper(props) {
|
|||||||
lineBorderWidth: props.lineBorderWidth,
|
lineBorderWidth: props.lineBorderWidth,
|
||||||
}), [props.showTooltip, props.showDataPoints, props.lineBorderWidth]);
|
}), [props.showTooltip, props.showDataPoints, props.lineBorderWidth]);
|
||||||
return (
|
return (
|
||||||
<>
|
<Box display="flex" flexDirection="column" height="100%">
|
||||||
<Grid container spacing={0.5} className={classes.container}>
|
<Grid container spacing={0.5} className={classes.container}>
|
||||||
<Grid item md={6}>
|
<Grid item md={6}>
|
||||||
<ChartContainer id='cu-graph' title={gettext('CPU usage')} datasets={props.cpuUsageInfo.datasets} errorMsg={props.errorMsg} isTest={props.isTest}>
|
<ChartContainer id='cu-graph' title={gettext('CPU usage')} datasets={props.cpuUsageInfo.datasets} errorMsg={props.errorMsg} isTest={props.isTest}>
|
||||||
@ -265,22 +266,20 @@ export function CPUWrapper(props) {
|
|||||||
</ChartContainer>
|
</ChartContainer>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid container spacing={0.5} className={classes.fixedContainer}>
|
<Box flexGrow={1} minHeight={0}>
|
||||||
<div className={classes.tableContainer}>
|
<SectionContainer title={gettext('Process CPU usage')}>
|
||||||
<PgTable
|
<PgTable
|
||||||
className={classes.autoResizer}
|
className={classes.autoResizer}
|
||||||
CustomHeader={() => {
|
|
||||||
return <div className={classes.containerHeader}>{gettext('Process CPU usage')}</div>;
|
|
||||||
}}
|
|
||||||
columns={props.tableHeader}
|
columns={props.tableHeader}
|
||||||
data={props.processCpuUsageStats}
|
data={props.processCpuUsageStats}
|
||||||
msg={props.errorMsg}
|
msg={props.errorMsg}
|
||||||
type={'panel'}
|
type={'panel'}
|
||||||
caveTable={false}
|
caveTable={false}
|
||||||
|
tableNoBorder={false}
|
||||||
></PgTable>
|
></PgTable>
|
||||||
</div>
|
</SectionContainer>
|
||||||
</Grid>
|
</Box>
|
||||||
</>
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@ import {useInterval, usePrevious} from 'sources/custom_hooks';
|
|||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { getStatsUrl, transformData, statsReducer, X_AXIS_LENGTH } from './utility.js';
|
import { getStatsUrl, transformData, statsReducer, X_AXIS_LENGTH } from './utility.js';
|
||||||
import { toPrettySize } from '../../../../static/js/utils';
|
import { toPrettySize } from '../../../../static/js/utils';
|
||||||
|
import SectionContainer from '../components/SectionContainer.jsx';
|
||||||
|
|
||||||
const useStyles = makeStyles((theme) => ({
|
const useStyles = makeStyles((theme) => ({
|
||||||
autoResizer: {
|
autoResizer: {
|
||||||
@ -255,7 +256,7 @@ export function MemoryWrapper(props) {
|
|||||||
}), [props.showTooltip, props.showDataPoints, props.lineBorderWidth]);
|
}), [props.showTooltip, props.showDataPoints, props.lineBorderWidth]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<Box display="flex" flexDirection="column" height="100%">
|
||||||
<Grid container spacing={0.5} className={classes.container}>
|
<Grid container spacing={0.5} className={classes.container}>
|
||||||
<Grid item md={6}>
|
<Grid item md={6}>
|
||||||
<ChartContainer id='m-graph' title={gettext('Memory')} datasets={props.memoryUsageInfo.datasets} errorMsg={props.errorMsg} isTest={props.isTest}>
|
<ChartContainer id='m-graph' title={gettext('Memory')} datasets={props.memoryUsageInfo.datasets} errorMsg={props.errorMsg} isTest={props.isTest}>
|
||||||
@ -270,22 +271,20 @@ export function MemoryWrapper(props) {
|
|||||||
</ChartContainer>
|
</ChartContainer>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid container spacing={0.5} className={classes.fixedContainer}>
|
<Box flexGrow={1} minHeight={0}>
|
||||||
<div className={classes.tableContainer}>
|
<SectionContainer title={gettext('Process memory usage')}>
|
||||||
<PgTable
|
<PgTable
|
||||||
className={classes.autoResizer}
|
className={classes.autoResizer}
|
||||||
CustomHeader={() => {
|
|
||||||
return <div className={classes.containerHeader}>{gettext('Process memory usage')}</div>;
|
|
||||||
}}
|
|
||||||
columns={props.tableHeader}
|
columns={props.tableHeader}
|
||||||
data={props.processMemoryUsageStats}
|
data={props.processMemoryUsageStats}
|
||||||
msg={props.errorMsg}
|
msg={props.errorMsg}
|
||||||
type={'panel'}
|
type={'panel'}
|
||||||
caveTable={false}
|
caveTable={false}
|
||||||
|
tableNoBorder={false}
|
||||||
></PgTable>
|
></PgTable>
|
||||||
</div>
|
</SectionContainer>
|
||||||
</Grid>
|
</Box>
|
||||||
</>
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@ import { getStatsUrl, transformData, X_AXIS_LENGTH } from './utility.js';
|
|||||||
import { toPrettySize } from '../../../../static/js/utils';
|
import { toPrettySize } from '../../../../static/js/utils';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import { commonTableStyles } from '../../../../static/js/Theme';
|
import { commonTableStyles } from '../../../../static/js/Theme';
|
||||||
|
import SectionContainer from '../components/SectionContainer.jsx';
|
||||||
|
|
||||||
const useStyles = makeStyles((theme) => ({
|
const useStyles = makeStyles((theme) => ({
|
||||||
container: {
|
container: {
|
||||||
@ -33,20 +34,8 @@ const useStyles = makeStyles((theme) => ({
|
|||||||
driveContainer: {
|
driveContainer: {
|
||||||
width: '100%',
|
width: '100%',
|
||||||
},
|
},
|
||||||
diskInfoContainer: {
|
|
||||||
height: 'auto',
|
|
||||||
padding: '8px 8px 0px 8px',
|
|
||||||
marginBottom: '0px',
|
|
||||||
},
|
|
||||||
diskInfoSummary: {
|
|
||||||
height: 'auto',
|
|
||||||
padding: '0px 0px 4px 0px',
|
|
||||||
marginBottom: '0px',
|
|
||||||
},
|
|
||||||
diskInfoCharts: {
|
diskInfoCharts: {
|
||||||
height: 'auto',
|
marginBottom: '4px',
|
||||||
padding: '0px 0px 2px 0px',
|
|
||||||
marginBottom: '0px',
|
|
||||||
},
|
},
|
||||||
containerHeaderText: {
|
containerHeaderText: {
|
||||||
fontWeight: 'bold',
|
fontWeight: 'bold',
|
||||||
@ -54,13 +43,12 @@ const useStyles = makeStyles((theme) => ({
|
|||||||
},
|
},
|
||||||
tableContainer: {
|
tableContainer: {
|
||||||
background: theme.otherVars.tableBg,
|
background: theme.otherVars.tableBg,
|
||||||
padding: '0px',
|
|
||||||
border: '1px solid '+theme.otherVars.borderColor,
|
border: '1px solid '+theme.otherVars.borderColor,
|
||||||
borderCollapse: 'collapse',
|
borderCollapse: 'collapse',
|
||||||
borderRadius: '4px',
|
borderRadius: '4px',
|
||||||
overflow: 'auto',
|
overflow: 'auto',
|
||||||
width: '100%',
|
width: '100%',
|
||||||
margin: '4px 4px 4px 4px',
|
marginBottom: '4px',
|
||||||
},
|
},
|
||||||
tableWhiteSpace: {
|
tableWhiteSpace: {
|
||||||
'& td, & th': {
|
'& td, & th': {
|
||||||
@ -143,7 +131,7 @@ const DiskStatsTable = (props) => {
|
|||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
{tableHeader.map((item, index) => (
|
{tableHeader.map((item, index) => (
|
||||||
<th key={index}>{item.Header}</th>
|
<th key={index}>{item.header}</th>
|
||||||
))}
|
))}
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
@ -151,7 +139,7 @@ const DiskStatsTable = (props) => {
|
|||||||
{data.map((item, index) => (
|
{data.map((item, index) => (
|
||||||
<tr key={index}>
|
<tr key={index}>
|
||||||
{tableHeader.map((header, id) => (
|
{tableHeader.map((header, id) => (
|
||||||
<td key={header.accessor+'-'+id}>{item[header.accessor]}</td>
|
<td key={header.accessorKey+'-'+id}>{item[header.accessorKey]}</td>
|
||||||
))}
|
))}
|
||||||
</tr>
|
</tr>
|
||||||
))}
|
))}
|
||||||
@ -428,14 +416,11 @@ export function StorageWrapper(props) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Grid container spacing={1} className={classes.diskInfoContainer}>
|
|
||||||
<Grid container spacing={1} className={classes.diskInfoSummary}>
|
|
||||||
<div className={classes.tableContainer}>
|
<div className={classes.tableContainer}>
|
||||||
<div className={classes.containerHeaderText}>{gettext('Disk information')}</div>
|
<div className={classes.containerHeaderText}>{gettext('Disk information')}</div>
|
||||||
<DiskStatsTable tableHeader={props.tableHeader} data={props.diskStats} />
|
<DiskStatsTable tableHeader={props.tableHeader} data={props.diskStats} />
|
||||||
</div>
|
</div>
|
||||||
</Grid>
|
<Grid container spacing={0.5} sx={{marginBottom: '4px'}}>
|
||||||
<Grid container spacing={1} className={classes.diskInfoCharts}>
|
|
||||||
<Grid item md={6} sm={12}>
|
<Grid item md={6} sm={12}>
|
||||||
<ChartContainer
|
<ChartContainer
|
||||||
id='t-space-graph'
|
id='t-space-graph'
|
||||||
@ -510,15 +495,9 @@ export function StorageWrapper(props) {
|
|||||||
</ChartContainer>
|
</ChartContainer>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
{Object.keys(props.ioInfo).map((drive) => (
|
||||||
<Grid container spacing={0.5} className={classes.container}>
|
<SectionContainer key={drive} title={drive} style={{minHeight: 'unset', height: 'auto', marginBottom: '0.5px'}}>
|
||||||
{Object.keys(props.ioInfo).map((drive, index) => (
|
<Grid container spacing={0.5} p={0.5}>
|
||||||
<Grid key={`disk-${index}`} container spacing={1} className={classes.container}>
|
|
||||||
<div className={classes.driveContainer}>
|
|
||||||
<Grid container spacing={1} className={classes.driveContainerHeader}>
|
|
||||||
<div className={classes.containerHeaderText}>{gettext(drive)}</div>
|
|
||||||
</Grid>
|
|
||||||
<Grid container spacing={0.5} className={classes.driveContainerBody}>
|
|
||||||
{Object.keys(props.ioInfo[drive]).map((type, innerKeyIndex) => (
|
{Object.keys(props.ioInfo[drive]).map((type, innerKeyIndex) => (
|
||||||
<Grid key={`${type}-${innerKeyIndex}`} item md={4} sm={6}>
|
<Grid key={`${type}-${innerKeyIndex}`} item md={4} sm={6}>
|
||||||
<ChartContainer id={`io-graph-${type}`} title={type.endsWith('_bytes_rw') ? gettext('Data transfer'): type.endsWith('_total_rw') ? gettext('I/O operations count'): type.endsWith('_time_rw') ? gettext('Time spent in I/O operations'):''} datasets={transformData(props.ioInfo[drive][type], props.ioRefreshRate).datasets} errorMsg={props.errorMsg} isTest={props.isTest}>
|
<ChartContainer id={`io-graph-${type}`} title={type.endsWith('_bytes_rw') ? gettext('Data transfer'): type.endsWith('_total_rw') ? gettext('I/O operations count'): type.endsWith('_time_rw') ? gettext('Time spent in I/O operations'):''} datasets={transformData(props.ioInfo[drive][type], props.ioRefreshRate).datasets} errorMsg={props.errorMsg} isTest={props.isTest}>
|
||||||
@ -530,10 +509,8 @@ export function StorageWrapper(props) {
|
|||||||
</Grid>
|
</Grid>
|
||||||
))}
|
))}
|
||||||
</Grid>
|
</Grid>
|
||||||
</div>
|
</SectionContainer>
|
||||||
</Grid>
|
|
||||||
))}
|
))}
|
||||||
</Grid>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -317,7 +317,7 @@ DataGridHeader.propTypes = {
|
|||||||
onSearchTextChange: PropTypes.func,
|
onSearchTextChange: PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
function DataGridView({
|
export default function DataGridView({
|
||||||
value, viewHelperProps, schema, accessPath, dataDispatch, containerClassName,
|
value, viewHelperProps, schema, accessPath, dataDispatch, containerClassName,
|
||||||
fixedRows, ...props}) {
|
fixedRows, ...props}) {
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
@ -639,14 +639,6 @@ function DataGridView({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function DataGridViewMoized({memoDeps, ...props}) {
|
|
||||||
return useMemo(()=><DataGridView {...props} />, memoDeps??[]);
|
|
||||||
}
|
|
||||||
|
|
||||||
DataGridViewMoized.propTypes = {
|
|
||||||
memoDeps: PropTypes.array,
|
|
||||||
};
|
|
||||||
|
|
||||||
DataGridView.propTypes = {
|
DataGridView.propTypes = {
|
||||||
label: PropTypes.string,
|
label: PropTypes.string,
|
||||||
value: PropTypes.array,
|
value: PropTypes.array,
|
||||||
|
@ -305,12 +305,7 @@ export default function FormView({
|
|||||||
if(CustomControl) {
|
if(CustomControl) {
|
||||||
tabs[group].push(<CustomControl {...ctrlProps}/>);
|
tabs[group].push(<CustomControl {...ctrlProps}/>);
|
||||||
} else {
|
} else {
|
||||||
tabs[group].push(<DataGridView {...ctrlProps} memoDeps={[
|
tabs[group].push(<DataGridView {...ctrlProps} />);
|
||||||
JSON.stringify(ctrlProps.value),
|
|
||||||
ctrlProps.containerClassName,
|
|
||||||
ctrlProps.visible,
|
|
||||||
...(evalFunc(null, ctrlProps.deps) || []).map((dep)=>value[dep]),
|
|
||||||
]} />);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Its a form control */
|
/* Its a form control */
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
//
|
//
|
||||||
//////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
import React, { forwardRef } from 'react';
|
import React, { forwardRef, useEffect } from 'react';
|
||||||
import { flexRender } from '@tanstack/react-table';
|
import { flexRender } from '@tanstack/react-table';
|
||||||
import { styled } from '@mui/styles';
|
import { styled } from '@mui/styles';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
@ -58,6 +58,12 @@ const StyledDiv = styled('div')(({theme})=>({
|
|||||||
...theme.mixins.panelBorder.bottom,
|
...theme.mixins.panelBorder.bottom,
|
||||||
...theme.mixins.panelBorder.right,
|
...theme.mixins.panelBorder.right,
|
||||||
|
|
||||||
|
'& > div': {
|
||||||
|
overflow: 'hidden',
|
||||||
|
textOverflow: 'ellipsis',
|
||||||
|
textWrap: 'nowrap'
|
||||||
|
},
|
||||||
|
|
||||||
'& .pgrt-header-resizer': {
|
'& .pgrt-header-resizer': {
|
||||||
display: 'inline-block',
|
display: 'inline-block',
|
||||||
width: '5px',
|
width: '5px',
|
||||||
@ -160,8 +166,8 @@ export const PgReactTableCell = forwardRef(({row, cell, children, className}, re
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={ref} key={cell.id} style={{
|
<div ref={ref} key={cell.id} style={{
|
||||||
flex: `var(--col-${cell.column.id}-size) 0 auto`,
|
flex: `var(--col-${cell.column.id.replace(/\W/g, '_')}-size) 0 auto`,
|
||||||
width: `calc(var(--col-${cell.column.id}-size)*1px)`,
|
width: `calc(var(--col-${cell.column.id.replace(/\W/g, '_')}-size)*1px)`,
|
||||||
...(cell.column.columnDef.maxSize ? { maxWidth: `${cell.column.columnDef.maxSize}px` } : {})
|
...(cell.column.columnDef.maxSize ? { maxWidth: `${cell.column.columnDef.maxSize}px` } : {})
|
||||||
}} role='cell'
|
}} role='cell'
|
||||||
className={clsx(...classNames)}
|
className={clsx(...classNames)}
|
||||||
@ -231,14 +237,14 @@ export function PgReactTableHeader({table}) {
|
|||||||
key={header.id}
|
key={header.id}
|
||||||
className='pgrt-header-cell'
|
className='pgrt-header-cell'
|
||||||
style={{
|
style={{
|
||||||
flex: `var(--header-${header?.id}-size) 0 auto`,
|
flex: `var(--header-${header?.id.replace(/\W/g, '_')}-size) 0 auto`,
|
||||||
width: `calc(var(--header-${header?.id}-size)*1px)`,
|
width: `calc(var(--header-${header?.id.replace(/\W/g, '_')}-size)*1px)`,
|
||||||
...(header.column.columnDef.maxSize ? { maxWidth: `${header.column.columnDef.maxSize}px` } : {}),
|
...(header.column.columnDef.maxSize ? { maxWidth: `${header.column.columnDef.maxSize}px` } : {}),
|
||||||
cursor: header.column.getCanSort() ? 'pointer' : 'initial',
|
cursor: header.column.getCanSort() ? 'pointer' : 'initial',
|
||||||
}}
|
}}
|
||||||
onClick={header.column.getCanSort() ? header.column.getToggleSortingHandler() : undefined}
|
onClick={header.column.getCanSort() ? header.column.getToggleSortingHandler() : undefined}
|
||||||
>
|
>
|
||||||
<div>
|
<div title={flexRender(header.column.columnDef.header, header.getContext())}>
|
||||||
{flexRender(header.column.columnDef.header, header.getContext())}
|
{flexRender(header.column.columnDef.header, header.getContext())}
|
||||||
{header.column.getCanSort() && header.column.getIsSorted() &&
|
{header.column.getCanSort() && header.column.getIsSorted() &&
|
||||||
<span>
|
<span>
|
||||||
@ -280,22 +286,32 @@ PgReactTableBody.propTypes = {
|
|||||||
|
|
||||||
export const PgReactTable = forwardRef(({children, table, rootClassName, tableClassName, ...props}, ref)=>{
|
export const PgReactTable = forwardRef(({children, table, rootClassName, tableClassName, ...props}, ref)=>{
|
||||||
const columns = table.getAllColumns();
|
const columns = table.getAllColumns();
|
||||||
// Render the UI for your table
|
|
||||||
const maxExpandWidth = (ref.current?.getBoundingClientRect().width ?? 430) - 30; //margin,scrollbar,etc.
|
useEffect(()=>{
|
||||||
|
const setMaxExpandWidth = ()=>{
|
||||||
|
if(ref.current) {
|
||||||
|
ref.current.style['--expand-width'] = (ref.current.getBoundingClientRect().width ?? 430) - 30; //margin,scrollbar,etc.
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const tableResizeObserver = new ResizeObserver(()=>{
|
||||||
|
setMaxExpandWidth();
|
||||||
|
});
|
||||||
|
tableResizeObserver.observe(ref.current);
|
||||||
|
}, []);
|
||||||
|
|
||||||
const columnSizeVars = React.useMemo(() => {
|
const columnSizeVars = React.useMemo(() => {
|
||||||
const headers = table.getFlatHeaders();
|
const headers = table.getFlatHeaders();
|
||||||
const colSizes = {};
|
const colSizes = {};
|
||||||
for (let i = 0; i < headers.length; i++) {
|
for (let i = 0; i < headers.length; i++) {
|
||||||
const header = headers[i];
|
const header = headers[i];
|
||||||
colSizes[`--header-${header.id}-size`] = header.getSize();
|
colSizes[`--header-${header.id.replace(/\W/g, '_')}-size`] = header.getSize();
|
||||||
colSizes[`--col-${header.column.id}-size`] = header.column.getSize();
|
colSizes[`--col-${header.column.id.replace(/\W/g, '_')}-size`] = header.column.getSize();
|
||||||
}
|
}
|
||||||
return colSizes;
|
return colSizes;
|
||||||
}, [columns, table.getState().columnSizingInfo]);
|
}, [columns, table.getState().columnSizingInfo]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledDiv className={clsx('pgrt', rootClassName)} style={{'--expand-width': maxExpandWidth }} ref={ref} >
|
<StyledDiv className={clsx('pgrt', rootClassName)} ref={ref} >
|
||||||
<div className={clsx('pgrt-table', tableClassName)} style={{ ...columnSizeVars }} {...props}>
|
<div className={clsx('pgrt-table', tableClassName)} style={{ ...columnSizeVars }} {...props}>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
|
@ -22,13 +22,14 @@ global.matchMedia = (query)=>({
|
|||||||
dispatchEvent: jest.fn(),
|
dispatchEvent: jest.fn(),
|
||||||
});
|
});
|
||||||
|
|
||||||
class IntersectionObserver {
|
class GeneralObserver {
|
||||||
observe() {return null;}
|
observe() {return null;}
|
||||||
unobserve() {return null;}
|
unobserve() {return null;}
|
||||||
disconnect() {return null;}
|
disconnect() {return null;}
|
||||||
}
|
}
|
||||||
|
|
||||||
global.IntersectionObserver = IntersectionObserver;
|
global.IntersectionObserver = GeneralObserver;
|
||||||
|
global.ResizeObserver = GeneralObserver;
|
||||||
|
|
||||||
import lodash from 'lodash';
|
import lodash from 'lodash';
|
||||||
global._ = lodash;
|
global._ = lodash;
|
||||||
|
Loading…
Reference in New Issue
Block a user