Skip to content

Commit

Permalink
Introduced 'useSchemaStateSubscriber', which generates a state
Browse files Browse the repository at this point in the history
subscriber mananager instance. It helps multiple subscribers in a
single control as we could have multiple subscribe within a control.
(For example - value, options, errors, etc).
  • Loading branch information
asheshv committed Sep 12, 2024
1 parent 581fdb6 commit 7c86328
Show file tree
Hide file tree
Showing 12 changed files with 168 additions and 76 deletions.
14 changes: 6 additions & 8 deletions web/pgadmin/static/js/SchemaView/DataGridView/grid.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ import CustomPropTypes from 'sources/custom_prop_types';

import { StyleDataGridBox } from '../StyledComponents';
import { SchemaStateContext } from '../SchemaState';
import { useFieldOptions, useFieldValue } from '../hooks';
import {
useFieldOptions, useFieldValue, useSchemaStateSubscriber,
} from '../hooks';
import { registerView } from '../registry';
import { listenDepChanges } from '../utils';

Expand All @@ -49,20 +51,16 @@ export default function DataGridView({
}) {
const pgAdmin = usePgAdmin();
const [refreshKey, setRefreshKey] = useState(0);
const subscriberManager = useSchemaStateSubscriber(setRefreshKey);
const schemaState = useContext(SchemaStateContext);
const options = useFieldOptions(
accessPath, schemaState, refreshKey, setRefreshKey
);
const options = useFieldOptions(accessPath, schemaState, subscriberManager);
const value = useFieldValue(accessPath, schemaState);
const schema = field.schema;
const features = useRef();

// Update refresh key on changing the number of rows.
useFieldValue(
[...accessPath, 'length'], schemaState, refreshKey,
(newKey) => {
setRefreshKey(newKey);
}
[...accessPath, 'length'], schemaState, subscriberManager
);

useEffect(() => {
Expand Down
13 changes: 9 additions & 4 deletions web/pgadmin/static/js/SchemaView/DataGridView/mappedCell.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ import { evalFunc } from 'sources/utils';
import { MappedCellControl } from '../MappedControl';
import { SCHEMA_STATE_ACTIONS, SchemaStateContext } from '../SchemaState';
import { flatternObject } from '../common';
import { useFieldOptions, useFieldValue } from '../hooks';
import {
useFieldOptions, useFieldValue, useSchemaStateSubscriber
} from '../hooks';
import { listenDepChanges } from '../utils';

import { DataGridContext, DataGridRowContext } from './context';
Expand All @@ -25,14 +27,17 @@ import { DataGridContext, DataGridRowContext } from './context';
export function getMappedCell({field}) {
const Cell = ({reRenderRow, getValue}) => {

const [key, setKey] = useState(0);
const [, setKey] = useState(0);
const subscriberManager = useSchemaStateSubscriber(setKey);
const schemaState = useContext(SchemaStateContext);
const { dataDispatch, accessPath } = useContext(DataGridContext);
const { rowAccessPath, row } = useContext(DataGridRowContext);
const colAccessPath = schemaState.accessPath(rowAccessPath, field.id);

let colOptions = useFieldOptions(colAccessPath, schemaState, key, setKey);
let value = useFieldValue(colAccessPath, schemaState, key, setKey);
let colOptions = useFieldOptions(
colAccessPath, schemaState, subscriberManager
);
let value = useFieldValue(colAccessPath, schemaState, subscriberManager);
let rowValue = useFieldValue(rowAccessPath, schemaState);

listenDepChanges(colAccessPath, field, true, schemaState);
Expand Down
10 changes: 7 additions & 3 deletions web/pgadmin/static/js/SchemaView/FieldSetView.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,25 @@ import CustomPropTypes from 'sources/custom_prop_types';

import { FieldControl } from './FieldControl';
import { SchemaStateContext } from './SchemaState';
import { useFieldSchema, useFieldValue } from './hooks';
import {
useFieldSchema, useFieldValue, useSchemaStateSubscriber,
} from './hooks';
import { registerView } from './registry';
import { createFieldControls, listenDepChanges } from './utils';


export default function FieldSetView({
field, accessPath, dataDispatch, viewHelperProps, controlClassName,
}) {
const [key, setRefreshKey] = useState(0);
const [, setKey] = useState(0);
const subscriberManager = useSchemaStateSubscriber(setKey);
const schema = field.schema;
const schemaState = useContext(SchemaStateContext);
const value = useFieldValue(accessPath, schemaState);
const options = useFieldSchema(
field, accessPath, value, viewHelperProps, schemaState, key, setRefreshKey
field, accessPath, value, viewHelperProps, schemaState, subscriberManager
);

const label = field.label;

listenDepChanges(accessPath, field, options.visible, schemaState);
Expand Down
18 changes: 10 additions & 8 deletions web/pgadmin/static/js/SchemaView/FormView.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ import { FieldControl } from './FieldControl';
import { SQLTab } from './SQLTab';
import { FormContentBox } from './StyledComponents';
import { SchemaStateContext } from './SchemaState';
import { useFieldSchema, useFieldValue } from './hooks';
import {
useFieldSchema, useFieldValue, useSchemaStateSubscriber,
} from './hooks';
import { registerView, View } from './registry';
import { createFieldControls, listenDepChanges } from './utils';

Expand Down Expand Up @@ -62,10 +64,11 @@ export default function FormView({
showError=false, resetKey, focusOnFirstInput=false
}) {
const [key, setKey] = useState(0);
const subscriberManager = useSchemaStateSubscriber(setKey);
const schemaState = useContext(SchemaStateContext);
const value = useFieldValue(accessPath, schemaState);
const { visible } = useFieldSchema(
field, accessPath, value, viewHelperProps, schemaState, key, setKey
field, accessPath, value, viewHelperProps, schemaState, subscriberManager
);

const [tabValue, setTabValue] = useState(0);
Expand Down Expand Up @@ -106,13 +109,12 @@ export default function FormView({

useEffect(() => {
// Refresh on message changes.
return schemaState.subscribe(
['errors', 'message'],
return subscriberManager.current?.add(
schemaState, ['errors', 'message'], 'states',
(newState, prevState) => {
if (_.isUndefined(newState) || _.isUndefined(prevState));
setKey(Date.now());
},
'states'
if (_.isUndefined(newState) || _.isUndefined(prevState))
subscriberManager.current?.signal();
}
);
}, [key]);

Expand Down
23 changes: 8 additions & 15 deletions web/pgadmin/static/js/SchemaView/MappedControl.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import { evalFunc } from 'sources/utils';
import { SchemaStateContext } from './SchemaState';
import { isValueEqual } from './common';
import {
useFieldOptions, useFieldValue, useFieldError
useFieldOptions, useFieldValue, useFieldError, useSchemaStateSubscriber,
} from './hooks';
import { listenDepChanges } from './utils';

Expand Down Expand Up @@ -339,22 +339,15 @@ export const MappedFormControl = ({
}) => {
const checkIsMounted = useIsMounted();
const [key, setKey] = useState(0);
const subscriberManager = useSchemaStateSubscriber(setKey);
const schemaState = useContext(SchemaStateContext);
const state = schemaState.data;
const avoidRenderingWhenNotMounted = (newKey) => {
if (checkIsMounted()) {
setKey(newKey);
}
const value = useFieldValue(accessPath, schemaState, subscriberManager);
const options = useFieldOptions(accessPath, schemaState, subscriberManager);
const {hasError} = useFieldError(accessPath, schemaState, subscriberManager);
const avoidRenderingWhenNotMounted = (...args) => {
if (checkIsMounted()) subscriberManager.current?.signal(...args);
};
const value = useFieldValue(
accessPath, schemaState, key, avoidRenderingWhenNotMounted
);
const options = useFieldOptions(
accessPath, schemaState, key, avoidRenderingWhenNotMounted
);
const { hasError } = useFieldError(
accessPath, schemaState, key, avoidRenderingWhenNotMounted
);

const origOnChange = onChange;

Expand All @@ -371,7 +364,7 @@ export const MappedFormControl = ({

const depVals = listenDepChanges(
accessPath, field, options.visible, schemaState, state,
key, avoidRenderingWhenNotMounted
avoidRenderingWhenNotMounted
);

let newProps = {
Expand Down
2 changes: 2 additions & 0 deletions web/pgadmin/static/js/SchemaView/hooks/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { useFieldOptions } from './useFieldOptions';
import { useFieldValue } from './useFieldValue';
import { useSchemaState } from './useSchemaState';
import { useFieldSchema } from './useFieldSchema';
import { useSchemaStateSubscriber } from './useSchemaStateSubscriber';


export {
Expand All @@ -20,4 +21,5 @@ export {
useFieldValue,
useFieldSchema,
useSchemaState,
useSchemaStateSubscriber,
};
15 changes: 8 additions & 7 deletions web/pgadmin/static/js/SchemaView/hooks/useFieldError.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,23 @@
import { useEffect } from 'react';


export const useFieldError = (
path, schemaState, key, setRefreshKey
) => {
export const useFieldError = (path, schemaState, subscriberManager) => {

useEffect(() => {
if (!schemaState || !setRefreshKey) return;
if (!schemaState || !subscriberManager?.current) return;

const checkPathError = (newState, prevState) => {
if (prevState.name !== path && newState.name !== path) return;
// We don't need to redraw the control on message change.
if (prevState.name === newState.name) return;

setRefreshKey({id: Date.now()});
subscriberManager.current?.signal();
};

return schemaState.subscribe(['errors'], checkPathError, 'states');
}, [key, schemaState?._id]);
return subscriberManager.current?.add(
schemaState, ['errors'], 'states', checkPathError
);
});

const errors = schemaState?.errors || {};
const error = errors.name === path ? errors.message : null;
Expand Down
13 changes: 5 additions & 8 deletions web/pgadmin/static/js/SchemaView/hooks/useFieldOptions.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,13 @@
import { useEffect } from 'react';


export const useFieldOptions = (
path, schemaState, key, setRefreshKey
) => {
export const useFieldOptions = (path, schemaState, subscriberManager) => {

useEffect(() => {
if (!schemaState) return;
if (!schemaState || !subscriberManager?.current) return;

return schemaState.subscribe(
path, () => setRefreshKey?.({id: Date.now()}), 'options'
);
}, [key, schemaState?._id]);
return subscriberManager.current?.add(schemaState, path, 'options');
});

return schemaState?.options(path) || {visible: true};
};
20 changes: 10 additions & 10 deletions web/pgadmin/static/js/SchemaView/hooks/useFieldSchema.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,32 +14,32 @@ import { booleanEvaluator } from '../options';


export const useFieldSchema = (
field, accessPath, value, viewHelperProps, schemaState, key, setRefreshKey
field, accessPath, value, viewHelperProps, schemaState, subscriberManager
) => {

useEffect(() => {
if (!schemaState || !field) return;
if (!schemaState || !field || !subscriberManager?.current) return;

// It already has 'id', 'options' is already evaluated.
if (field.id)
return schemaState.subscribe(
accessPath, () => setRefreshKey?.({id: Date.now()}), 'options'
);
return subscriberManager.current?.add(schemaState, accessPath, 'options');

// There are no dependencies.
if (!_.isArray(field?.deps)) return;

// Subscribe to all the dependents.
const unsubscribers = field.deps.map((dep) => (
schemaState.subscribe(
accessPath.concat(dep), () => setRefreshKey?.({id: Date.now()}),
'value'
subscriberManager.current?.add(
schemaState, accessPath.concat(dep), 'value'
)
));

return () => {
unsubscribers.forEach(unsubscribe => unsubscribe());
unsubscribers.forEach(
unsubscribe => subscriberManager.current?.remove(unsubscribe)
);
};
}, [key, schemaState?._id]);
});

if (!field) return { visible: true };
if (field.id) return schemaState?.options(accessPath);
Expand Down
13 changes: 5 additions & 8 deletions web/pgadmin/static/js/SchemaView/hooks/useFieldValue.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,13 @@
import { useEffect } from 'react';


export const useFieldValue = (
path, schemaState, key, setRefreshKey
) => {
export const useFieldValue = (path, schemaState, subscriberManager) => {

useEffect(() => {
if (!schemaState || !setRefreshKey) return;
if (!schemaState || !subscriberManager?.current) return;

return schemaState.subscribe(
path, () => setRefreshKey({id: Date.now()}), 'value'
);
}, [key, schemaState?._id]);
return subscriberManager.current?.add(schemaState, path, 'value');
});

return schemaState?.value(path);
};
Loading

0 comments on commit 7c86328

Please sign in to comment.