mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-15 01:12:56 +03:00
console (refactor): remove redundant metadata invalidations
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/9675 GitOrigin-RevId: 4a34f9f4ba09e8437824573dd3522fb4737a89d6
This commit is contained in:
parent
216f6a8f30
commit
f238e7a28a
@ -177,6 +177,6 @@ export {
|
|||||||
removeLSItem,
|
removeLSItem,
|
||||||
} from './lib/utils/localStorage';
|
} from './lib/utils/localStorage';
|
||||||
|
|
||||||
export { listenForStoreMetadataChanges } from './lib/store.utils';
|
export { reduxStoreListener } from './lib/store/utils/';
|
||||||
|
|
||||||
export { default as App } from './lib/components/App/App';
|
export { default as App } from './lib/components/App/App';
|
||||||
|
@ -1,14 +1,17 @@
|
|||||||
import { Dispatch } from '../../../../../../types';
|
import {
|
||||||
|
useInvalidateMetadata,
|
||||||
|
useMetadata,
|
||||||
|
} from '../../../../../../features/hasura-metadata-api';
|
||||||
import { reactQueryClient } from '../../../../../../lib/reactQuery';
|
import { reactQueryClient } from '../../../../../../lib/reactQuery';
|
||||||
|
import { Dispatch } from '../../../../../../types';
|
||||||
|
import _push from '../../../push';
|
||||||
import { NeonBanner } from './components/Neon/NeonBanner';
|
import { NeonBanner } from './components/Neon/NeonBanner';
|
||||||
|
import { FETCH_NEON_PROJECTS_BY_PROJECTID_QUERYKEY } from './components/NeonDashboardLink';
|
||||||
|
import { useNeonIntegration } from './useNeonIntegration';
|
||||||
import {
|
import {
|
||||||
getNeonDBName,
|
getNeonDBName,
|
||||||
transformNeonIntegrationStatusToNeonBannerProps,
|
transformNeonIntegrationStatusToNeonBannerProps,
|
||||||
} from './utils';
|
} from './utils';
|
||||||
import { useNeonIntegration } from './useNeonIntegration';
|
|
||||||
import _push from '../../../push';
|
|
||||||
import { FETCH_NEON_PROJECTS_BY_PROJECTID_QUERYKEY } from './components/NeonDashboardLink';
|
|
||||||
import { useMetadata } from '../../../../../../features/hasura-metadata-api';
|
|
||||||
|
|
||||||
type NeonConnectProps = {
|
type NeonConnectProps = {
|
||||||
dispatch: Dispatch;
|
dispatch: Dispatch;
|
||||||
@ -19,7 +22,8 @@ export function NeonConnect({
|
|||||||
dispatch,
|
dispatch,
|
||||||
connectDbUrl = '/data/manage/connect',
|
connectDbUrl = '/data/manage/connect',
|
||||||
}: NeonConnectProps) {
|
}: NeonConnectProps) {
|
||||||
const { data, invalidateMetadata } = useMetadata();
|
const { data } = useMetadata();
|
||||||
|
const invalidateMetadata = useInvalidateMetadata();
|
||||||
const allDatabases = data?.metadata.sources.map(source => source.name) ?? [];
|
const allDatabases = data?.metadata.sources.map(source => source.name) ?? [];
|
||||||
|
|
||||||
// success callback
|
// success callback
|
||||||
@ -29,7 +33,10 @@ export function NeonConnect({
|
|||||||
reactQueryClient.refetchQueries(FETCH_NEON_PROJECTS_BY_PROJECTID_QUERYKEY);
|
reactQueryClient.refetchQueries(FETCH_NEON_PROJECTS_BY_PROJECTID_QUERYKEY);
|
||||||
|
|
||||||
// invalidate react query metadata on success
|
// invalidate react query metadata on success
|
||||||
invalidateMetadata();
|
invalidateMetadata({
|
||||||
|
componentName: 'NeonConnect',
|
||||||
|
reasons: ['Successfully adding neon source.'],
|
||||||
|
});
|
||||||
|
|
||||||
dispatch(_push(`/data/${dataSourceName}/schema/public`));
|
dispatch(_push(`/data/${dataSourceName}/schema/public`));
|
||||||
};
|
};
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { getDriverPrefix } from '../../../../../../../features/DataSource';
|
import { getDriverPrefix } from '../../../../../../../features/DataSource';
|
||||||
import { useInvalidateMetadata } from '../../../../../../../features/hasura-metadata-api';
|
|
||||||
import {
|
import {
|
||||||
QualifiedFunction,
|
QualifiedFunction,
|
||||||
SupportedDrivers,
|
SupportedDrivers,
|
||||||
@ -40,11 +39,8 @@ type Props = {
|
|||||||
export const useSetFunctionCustomization = ({ onSuccess, onError }: Props) => {
|
export const useSetFunctionCustomization = ({ onSuccess, onError }: Props) => {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
const invalidateMetadata = useInvalidateMetadata();
|
|
||||||
|
|
||||||
const mutation = useMetadataMigration({
|
const mutation = useMetadataMigration({
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
invalidateMetadata();
|
|
||||||
dispatch(updateSchemaInfo()).then(() => {
|
dispatch(updateSchemaInfo()).then(() => {
|
||||||
if (onSuccess) {
|
if (onSuccess) {
|
||||||
onSuccess();
|
onSuccess();
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { FaExclamationTriangle } from 'react-icons/fa';
|
||||||
import { Source } from '../../../../../features/hasura-metadata-types';
|
import { Source } from '../../../../../features/hasura-metadata-types';
|
||||||
import { exportMetadata } from '../../../../../metadata/actions';
|
import { exportMetadata } from '../../../../../metadata/actions';
|
||||||
import { Button } from '../../../../../new-components/Button';
|
import { Button } from '../../../../../new-components/Button';
|
||||||
import { Tooltip } from '../../../../../new-components/Tooltip';
|
import { Tooltip } from '../../../../../new-components/Tooltip';
|
||||||
import { Dispatch } from '../../../../../types';
|
import { Dispatch } from '../../../../../types';
|
||||||
import React from 'react';
|
|
||||||
import { FaExclamationTriangle } from 'react-icons/fa';
|
|
||||||
import { useQueryClient } from 'react-query';
|
|
||||||
import _push from '../../push';
|
import _push from '../../push';
|
||||||
import { isInconsistentSource } from '../../utils';
|
import { isInconsistentSource } from '../../utils';
|
||||||
import { useDropSource } from '../hooks/useDropSource';
|
import { useDropSource } from '../hooks/useDropSource';
|
||||||
@ -17,16 +16,15 @@ type GDCDatabaseListItemItemProps = {
|
|||||||
dispatch: Dispatch;
|
dispatch: Dispatch;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// This appears to be dead code that's not referenced or implemented anywhere:
|
||||||
export const GDCDatabaseListItem: React.FC<GDCDatabaseListItemItemProps> = ({
|
export const GDCDatabaseListItem: React.FC<GDCDatabaseListItemItemProps> = ({
|
||||||
dataSource,
|
dataSource,
|
||||||
inconsistentObjects,
|
inconsistentObjects,
|
||||||
dispatch,
|
dispatch,
|
||||||
}) => {
|
}) => {
|
||||||
const queryClient = useQueryClient();
|
|
||||||
const { dropSource, isLoading: isDropSourceInProgress } = useDropSource({
|
const { dropSource, isLoading: isDropSourceInProgress } = useDropSource({
|
||||||
customOnSuccess: () => {
|
customOnSuccess: () => {
|
||||||
dispatch(exportMetadata());
|
dispatch(exportMetadata());
|
||||||
queryClient.invalidateQueries(['export_metadata']);
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
import React, { useReducer } from 'react';
|
import { useReducer } from 'react';
|
||||||
import { useQueryClient } from 'react-query';
|
|
||||||
import { RemoteDBRelationship } from '../../../../../metadata/types';
|
|
||||||
import { NormalizedTable } from '../../../../../dataSources/types';
|
import { NormalizedTable } from '../../../../../dataSources/types';
|
||||||
|
import { useInvalidateMetadata } from '../../../../../features/hasura-metadata-api';
|
||||||
|
import { RemoteDBRelationship } from '../../../../../metadata/types';
|
||||||
import { Dispatch } from '../../../../../types';
|
import { Dispatch } from '../../../../../types';
|
||||||
|
import ExpandableEditor from '../../../../Common/Layout/ExpandableEditor/Editor';
|
||||||
import { ordinalColSort } from '../../utils';
|
import { ordinalColSort } from '../../utils';
|
||||||
import { addDbToDbRelationship, dropDbToDbRelationship } from '../Actions';
|
import { addDbToDbRelationship, dropDbToDbRelationship } from '../Actions';
|
||||||
import {
|
|
||||||
relResetState,
|
|
||||||
dbToDbRelDefaultState,
|
|
||||||
dbToDbRelReducer,
|
|
||||||
} from './state';
|
|
||||||
import ExpandableEditor from '../../../../Common/Layout/ExpandableEditor/Editor';
|
|
||||||
import ManualRelationshipSelector from './ManualRelationshipSelector';
|
import ManualRelationshipSelector from './ManualRelationshipSelector';
|
||||||
import { RemoteRelCollapsedLabel } from './RemoteRelCollapsedLabel';
|
import { RemoteRelCollapsedLabel } from './RemoteRelCollapsedLabel';
|
||||||
|
import {
|
||||||
|
dbToDbRelDefaultState,
|
||||||
|
dbToDbRelReducer,
|
||||||
|
relResetState,
|
||||||
|
} from './state';
|
||||||
import { parseDbToDbRemoteRel } from './utils';
|
import { parseDbToDbRemoteRel } from './utils';
|
||||||
|
|
||||||
const AddManualRelationship = ({
|
const AddManualRelationship = ({
|
||||||
@ -32,7 +32,7 @@ const AddManualRelationship = ({
|
|||||||
);
|
);
|
||||||
const columns = tableSchema.columns.sort(ordinalColSort);
|
const columns = tableSchema.columns.sort(ordinalColSort);
|
||||||
const isNew = relationship === null;
|
const isNew = relationship === null;
|
||||||
const queryClient = useQueryClient();
|
const invalidate = useInvalidateMetadata();
|
||||||
|
|
||||||
// columns in the right order with their indices
|
// columns in the right order with their indices
|
||||||
const orderedColumns = columns.map((c, i) => ({
|
const orderedColumns = columns.map((c, i) => ({
|
||||||
@ -51,7 +51,10 @@ const AddManualRelationship = ({
|
|||||||
reduxDispatch(
|
reduxDispatch(
|
||||||
dropDbToDbRelationship(state, tableSchema, () => {
|
dropDbToDbRelationship(state, tableSchema, () => {
|
||||||
toggleEditor();
|
toggleEditor();
|
||||||
queryClient.refetchQueries(['metadata'], { active: true });
|
invalidate({
|
||||||
|
componentName: 'AddManualRelationship',
|
||||||
|
reasons: ['Dropped db-to-db relationship'],
|
||||||
|
});
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -60,10 +63,12 @@ const AddManualRelationship = ({
|
|||||||
const saveFk = (toggleEditor: unknown) => {
|
const saveFk = (toggleEditor: unknown) => {
|
||||||
reduxDispatch(
|
reduxDispatch(
|
||||||
addDbToDbRelationship(state, tableSchema, toggleEditor, isNew, () => {
|
addDbToDbRelationship(state, tableSchema, toggleEditor, isNew, () => {
|
||||||
queryClient.refetchQueries(['metadata'], { active: true });
|
invalidate({
|
||||||
|
componentName: 'AddManualRelationship',
|
||||||
|
reasons: ['Added db-to-db relationship'],
|
||||||
|
});
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
// queryClient.refetchQueries(['metadata'], { active: true });
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const expandedContent = () => (
|
const expandedContent = () => (
|
||||||
|
@ -1,22 +1,22 @@
|
|||||||
|
import { useDispatch, useStore } from 'react-redux';
|
||||||
|
import { Link } from 'react-router';
|
||||||
import {
|
import {
|
||||||
createActionMigration,
|
createActionMigration,
|
||||||
deleteAction,
|
deleteAction,
|
||||||
executeActionCreation,
|
executeActionCreation,
|
||||||
} from '../../../../components/Services/Actions/ServerIO';
|
} from '../../../../components/Services/Actions/ServerIO';
|
||||||
import { Link } from 'react-router';
|
|
||||||
import { useMetadata } from '../../../MetadataAPI';
|
|
||||||
import { useDispatch, useStore } from 'react-redux';
|
|
||||||
import { GeneratedAction } from './types';
|
|
||||||
import { parseCustomTypes } from '../../../../shared/utils/hasuraCustomTypeUtils';
|
import { parseCustomTypes } from '../../../../shared/utils/hasuraCustomTypeUtils';
|
||||||
|
import { useMetadata } from '../../../MetadataAPI';
|
||||||
import { generatedActionToHasuraAction } from '../OASGenerator/utils';
|
import { generatedActionToHasuraAction } from '../OASGenerator/utils';
|
||||||
|
import { GeneratedAction } from './types';
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
import { FaAngleRight, FaFileImport, FaHome } from 'react-icons/fa';
|
import { FaAngleRight, FaFileImport, FaHome } from 'react-icons/fa';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
import { useQueryClient } from 'react-query';
|
|
||||||
import { SimpleForm } from '../../../../new-components/Form';
|
|
||||||
import { OasGeneratorForm } from './OASGeneratorForm';
|
|
||||||
import React from 'react';
|
|
||||||
import { useLocalStorage } from '../../../../hooks';
|
import { useLocalStorage } from '../../../../hooks';
|
||||||
|
import { SimpleForm } from '../../../../new-components/Form';
|
||||||
|
import { useInvalidateMetadata } from '../../../hasura-metadata-api';
|
||||||
|
import { OasGeneratorForm } from './OASGeneratorForm';
|
||||||
|
|
||||||
export const formSchema = z.object({
|
export const formSchema = z.object({
|
||||||
oas: z.string(),
|
oas: z.string(),
|
||||||
@ -49,7 +49,7 @@ export const Breadcrumbs = () => (
|
|||||||
export const OASGeneratorPage = () => {
|
export const OASGeneratorPage = () => {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const store = useStore();
|
const store = useStore();
|
||||||
const queryClient = useQueryClient();
|
const invalidateMetadata = useInvalidateMetadata();
|
||||||
|
|
||||||
const [savedOas, setSavedOas] = useLocalStorage<string>('oas', '');
|
const [savedOas, setSavedOas] = useLocalStorage<string>('oas', '');
|
||||||
|
|
||||||
@ -77,7 +77,10 @@ export const OASGeneratorPage = () => {
|
|||||||
state,
|
state,
|
||||||
false,
|
false,
|
||||||
() => {
|
() => {
|
||||||
queryClient.invalidateQueries(['metadata']);
|
invalidateMetadata({
|
||||||
|
componentName: 'OASGeneratorPage',
|
||||||
|
reasons: ['onGenerate action migration occurred'],
|
||||||
|
});
|
||||||
setBusy(false);
|
setBusy(false);
|
||||||
},
|
},
|
||||||
() => {
|
() => {
|
||||||
@ -99,7 +102,10 @@ export const OASGeneratorPage = () => {
|
|||||||
store.getState,
|
store.getState,
|
||||||
false,
|
false,
|
||||||
() => {
|
() => {
|
||||||
queryClient.invalidateQueries(['metadata']);
|
invalidateMetadata({
|
||||||
|
componentName: 'OASGeneratorPage',
|
||||||
|
reasons: ['onDelete delete action occurred'],
|
||||||
|
});
|
||||||
setBusy(false);
|
setBusy(false);
|
||||||
},
|
},
|
||||||
() => {
|
() => {
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
import { useQueryClient } from 'react-query';
|
import { useQueryClient } from 'react-query';
|
||||||
|
import { useDispatch } from 'react-redux';
|
||||||
import { push } from 'react-router-redux';
|
import { push } from 'react-router-redux';
|
||||||
import { SupportedDrivers } from '../../hasura-metadata-types';
|
|
||||||
import { allowedMetadataTypes, useMetadataMigration } from '../../MetadataAPI';
|
|
||||||
import { APIError } from '../../../hooks/error';
|
import { APIError } from '../../../hooks/error';
|
||||||
|
import { exportMetadata } from '../../../metadata/actions';
|
||||||
import { useFireNotification } from '../../../new-components/Notifications';
|
import { useFireNotification } from '../../../new-components/Notifications';
|
||||||
import { getDriverPrefix } from '../../DataSource';
|
import { getDriverPrefix } from '../../DataSource';
|
||||||
import { exportMetadata } from '../../../metadata/actions';
|
import { allowedMetadataTypes, useMetadataMigration } from '../../MetadataAPI';
|
||||||
|
import { SupportedDrivers } from '../../hasura-metadata-types';
|
||||||
import { useAvailableDrivers } from './useAvailableDrivers';
|
import { useAvailableDrivers } from './useAvailableDrivers';
|
||||||
import { useDispatch } from 'react-redux';
|
|
||||||
|
|
||||||
type UseRedirectArgs = {
|
type UseRedirectArgs = {
|
||||||
redirectWithLatencyCheck: boolean;
|
redirectWithLatencyCheck: boolean;
|
||||||
@ -48,7 +48,6 @@ export const useSubmit = () => {
|
|||||||
const drivers = useAvailableDrivers();
|
const drivers = useAvailableDrivers();
|
||||||
const { fireNotification } = useFireNotification();
|
const { fireNotification } = useFireNotification();
|
||||||
const redirect = useRedirect({ redirectWithLatencyCheck: false });
|
const redirect = useRedirect({ redirectWithLatencyCheck: false });
|
||||||
const queryClient = useQueryClient();
|
|
||||||
|
|
||||||
const { mutate, ...rest } = useMetadataMigration({
|
const { mutate, ...rest } = useMetadataMigration({
|
||||||
onError: (error: APIError) => {
|
onError: (error: APIError) => {
|
||||||
@ -59,8 +58,6 @@ export const useSubmit = () => {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
queryClient.invalidateQueries(['export_metadata']);
|
|
||||||
|
|
||||||
fireNotification({
|
fireNotification({
|
||||||
type: 'success',
|
type: 'success',
|
||||||
title: 'Success',
|
title: 'Success',
|
||||||
|
@ -6,7 +6,6 @@ import Skeleton from 'react-loading-skeleton';
|
|||||||
import globals from '../../../../Globals';
|
import globals from '../../../../Globals';
|
||||||
import _push from '../../../../components/Services/Data/push';
|
import _push from '../../../../components/Services/Data/push';
|
||||||
import { exportMetadata } from '../../../../metadata/actions';
|
import { exportMetadata } from '../../../../metadata/actions';
|
||||||
import { MetadataDataSource } from '../../../../metadata/types';
|
|
||||||
import { useDestructiveAlert } from '../../../../new-components/Alert';
|
import { useDestructiveAlert } from '../../../../new-components/Alert';
|
||||||
import { Button } from '../../../../new-components/Button';
|
import { Button } from '../../../../new-components/Button';
|
||||||
import { CardedTable } from '../../../../new-components/CardedTable';
|
import { CardedTable } from '../../../../new-components/CardedTable';
|
||||||
@ -14,7 +13,9 @@ import { IndicatorCard } from '../../../../new-components/IndicatorCard';
|
|||||||
import { hasuraToast } from '../../../../new-components/Toasts';
|
import { hasuraToast } from '../../../../new-components/Toasts';
|
||||||
import { useAppDispatch } from '../../../../storeHooks';
|
import { useAppDispatch } from '../../../../storeHooks';
|
||||||
import { getProjectId, isCloudConsole } from '../../../../utils/cloudConsole';
|
import { getProjectId, isCloudConsole } from '../../../../utils/cloudConsole';
|
||||||
import { useMetadata } from '../../../MetadataAPI';
|
|
||||||
|
import { useMetadata } from '../../../hasura-metadata-api';
|
||||||
|
import { Source } from '../../../hasura-metadata-types';
|
||||||
import { useDatabaseLatencyCheck } from '../../hooks/useDatabaseLatencyCheck';
|
import { useDatabaseLatencyCheck } from '../../hooks/useDatabaseLatencyCheck';
|
||||||
import { useDatabaseVersion } from '../../hooks/useDatabaseVersion';
|
import { useDatabaseVersion } from '../../hooks/useDatabaseVersion';
|
||||||
import { useDropSource } from '../../hooks/useDropSource';
|
import { useDropSource } from '../../hooks/useDropSource';
|
||||||
@ -25,8 +26,8 @@ import { Latency } from '../../types';
|
|||||||
import { AccelerateProject, Details, LatencyBadge } from './parts';
|
import { AccelerateProject, Details, LatencyBadge } from './parts';
|
||||||
|
|
||||||
type DatabaseItem = {
|
type DatabaseItem = {
|
||||||
dataSourceName: MetadataDataSource['name'];
|
dataSourceName: Source['name'];
|
||||||
driver: MetadataDataSource['kind'];
|
driver: Source['kind'];
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ListConnectedDatabases = (props?: { className?: string }) => {
|
export const ListConnectedDatabases = (props?: { className?: string }) => {
|
||||||
@ -88,7 +89,10 @@ export const ListConnectedDatabases = (props?: { className?: string }) => {
|
|||||||
!isFetching
|
!isFetching
|
||||||
);
|
);
|
||||||
|
|
||||||
const isCurrentRow = (rowIndex: number) => rowIndex === activeRow;
|
const isCurrentRow = React.useCallback(
|
||||||
|
(rowIndex: number) => rowIndex === activeRow,
|
||||||
|
[activeRow]
|
||||||
|
);
|
||||||
|
|
||||||
const columns = ['database', 'driver', '', ''];
|
const columns = ['database', 'driver', '', ''];
|
||||||
|
|
||||||
@ -128,7 +132,7 @@ export const ListConnectedDatabases = (props?: { className?: string }) => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
[dropSource]
|
[destructivePrompt, dropSource]
|
||||||
);
|
);
|
||||||
|
|
||||||
const rowData = React.useMemo(
|
const rowData = React.useMemo(
|
||||||
@ -193,6 +197,8 @@ export const ListConnectedDatabases = (props?: { className?: string }) => {
|
|||||||
[
|
[
|
||||||
databaseList,
|
databaseList,
|
||||||
databaseVersions,
|
databaseVersions,
|
||||||
|
handleEdit,
|
||||||
|
handleRemove,
|
||||||
inconsistentSources,
|
inconsistentSources,
|
||||||
isCurrentRow,
|
isCurrentRow,
|
||||||
isDatabaseVersionLoading,
|
isDatabaseVersionLoading,
|
||||||
@ -209,7 +215,8 @@ export const ListConnectedDatabases = (props?: { className?: string }) => {
|
|||||||
// isLoading: isUpdatingProjectRegion,
|
// isLoading: isUpdatingProjectRegion,
|
||||||
} = useUpdateProjectRegion();
|
} = useUpdateProjectRegion();
|
||||||
|
|
||||||
const openUpdateProjectRegionPage = React.useCallback((_rowId?: string) => {
|
const openUpdateProjectRegionPage = React.useCallback(
|
||||||
|
(_rowId?: string) => {
|
||||||
if (!_rowId) {
|
if (!_rowId) {
|
||||||
hasuraToast({
|
hasuraToast({
|
||||||
type: 'error',
|
type: 'error',
|
||||||
@ -231,7 +238,9 @@ export const ListConnectedDatabases = (props?: { className?: string }) => {
|
|||||||
const cloudDetailsPage = `${window.location.protocol}//${window.location.host}/project/${projectId}/details?open_update_region_drawer=true`;
|
const cloudDetailsPage = `${window.location.protocol}//${window.location.host}/project/${projectId}/details?open_update_region_drawer=true`;
|
||||||
|
|
||||||
window.open(cloudDetailsPage, '_blank');
|
window.open(cloudDetailsPage, '_blank');
|
||||||
}, []);
|
},
|
||||||
|
[updateProjectRegionForRowId]
|
||||||
|
);
|
||||||
|
|
||||||
if (isLoading) return <>Loading...</>;
|
if (isLoading) return <>Loading...</>;
|
||||||
|
|
||||||
|
@ -1,19 +1,18 @@
|
|||||||
import { useInvalidateMetadata } from '../../hasura-metadata-api';
|
|
||||||
import { useMetadataMigration } from '../../MetadataAPI';
|
|
||||||
import { hasuraToast } from '../../../new-components/Toasts';
|
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import { MetadataMigrationOptions } from '../../MetadataAPI/hooks/useMetadataMigration';
|
|
||||||
import { useAppDispatch } from '../../../storeHooks';
|
|
||||||
import { UPDATE_CURRENT_DATA_SOURCE } from '../../../components/Services/Data/DataActions';
|
import { UPDATE_CURRENT_DATA_SOURCE } from '../../../components/Services/Data/DataActions';
|
||||||
|
import { hasuraToast } from '../../../new-components/Toasts';
|
||||||
|
import { useAppDispatch } from '../../../storeHooks';
|
||||||
|
import { useMetadataMigration } from '../../MetadataAPI';
|
||||||
|
import { MetadataMigrationOptions } from '../../MetadataAPI/hooks/useMetadataMigration';
|
||||||
|
|
||||||
export const useDropSource = (props?: MetadataMigrationOptions) => {
|
export const useDropSource = (props?: MetadataMigrationOptions) => {
|
||||||
const { ...globalMutateOptions } = props;
|
const { ...globalMutateOptions } = props;
|
||||||
|
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const invalidateMetadata = useInvalidateMetadata();
|
|
||||||
const { mutate, ...rest } = useMetadataMigration({
|
const { mutate, ...rest } = useMetadataMigration({
|
||||||
onSuccess: (data, variables, ctx) => {
|
onSuccess: (data, variables, ctx) => {
|
||||||
hasuraToast({ type: 'success', title: 'Source dropped from metadata!' });
|
hasuraToast({ type: 'success', title: 'Source dropped from metadata!' });
|
||||||
invalidateMetadata();
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: UPDATE_CURRENT_DATA_SOURCE,
|
type: UPDATE_CURRENT_DATA_SOURCE,
|
||||||
source: '',
|
source: '',
|
||||||
|
@ -1,18 +1,16 @@
|
|||||||
import { useCallback, useMemo } from 'react';
|
import { useCallback, useMemo } from 'react';
|
||||||
import { useQueryClient } from 'react-query';
|
import { Driver } from '../../../dataSources';
|
||||||
import { exportMetadata } from '../../../metadata/actions';
|
import { exportMetadata } from '../../../metadata/actions';
|
||||||
import { useAppDispatch } from '../../../storeHooks';
|
import { useAppDispatch } from '../../../storeHooks';
|
||||||
import { generateQueryKeys } from '../../DatabaseRelationships/utils/queryClientUtils';
|
|
||||||
import { useMetadataMigration } from '../../MetadataAPI';
|
import { useMetadataMigration } from '../../MetadataAPI';
|
||||||
|
import { useHttpClient } from '../../Network';
|
||||||
|
import { useMetadata } from '../../hasura-metadata-api';
|
||||||
import { DatabaseConnection } from '../types';
|
import { DatabaseConnection } from '../types';
|
||||||
import { usePushRoute } from './usePushRoute';
|
|
||||||
import {
|
import {
|
||||||
sendConnectDatabaseTelemetryEvent,
|
sendConnectDatabaseTelemetryEvent,
|
||||||
transformErrorResponse,
|
transformErrorResponse,
|
||||||
} from '../utils';
|
} from '../utils';
|
||||||
import { useHttpClient } from '../../Network';
|
import { usePushRoute } from './usePushRoute';
|
||||||
import { Driver } from '../../../dataSources';
|
|
||||||
import { useMetadata } from '../../hasura-metadata-api';
|
|
||||||
|
|
||||||
export const useManageDatabaseConnection = ({
|
export const useManageDatabaseConnection = ({
|
||||||
onSuccess,
|
onSuccess,
|
||||||
@ -21,7 +19,6 @@ export const useManageDatabaseConnection = ({
|
|||||||
onSuccess?: () => void;
|
onSuccess?: () => void;
|
||||||
onError?: (err: Error) => void;
|
onError?: (err: Error) => void;
|
||||||
}) => {
|
}) => {
|
||||||
const queryClient = useQueryClient();
|
|
||||||
const { mutateAsync, ...rest } = useMetadataMigration({
|
const { mutateAsync, ...rest } = useMetadataMigration({
|
||||||
errorTransform: transformErrorResponse,
|
errorTransform: transformErrorResponse,
|
||||||
});
|
});
|
||||||
@ -33,7 +30,6 @@ export const useManageDatabaseConnection = ({
|
|||||||
const mutationOptions = useMemo(
|
const mutationOptions = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
queryClient.invalidateQueries(generateQueryKeys.metadata());
|
|
||||||
onSuccess?.();
|
onSuccess?.();
|
||||||
|
|
||||||
// this code is only for the demo
|
// this code is only for the demo
|
||||||
@ -45,7 +41,7 @@ export const useManageDatabaseConnection = ({
|
|||||||
onError?.(err);
|
onError?.(err);
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
[dispatch, onError, onSuccess, push, queryClient]
|
[dispatch, onError, onSuccess, push]
|
||||||
);
|
);
|
||||||
|
|
||||||
const createConnection = useCallback(
|
const createConnection = useCallback(
|
||||||
|
@ -1,15 +1,11 @@
|
|||||||
import { useMetadataMigration } from '../../MetadataAPI';
|
|
||||||
import { useInvalidateMetadata } from '../../hasura-metadata-api';
|
|
||||||
import { hasuraToast } from '../../../new-components/Toasts';
|
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
|
import { hasuraToast } from '../../../new-components/Toasts';
|
||||||
|
import { useMetadataMigration } from '../../MetadataAPI';
|
||||||
|
|
||||||
export const useReloadSource = () => {
|
export const useReloadSource = () => {
|
||||||
const invalidateMetadata = useInvalidateMetadata();
|
|
||||||
|
|
||||||
const { mutate, ...rest } = useMetadataMigration({
|
const { mutate, ...rest } = useMetadataMigration({
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
hasuraToast({ type: 'success', title: 'Reload successful!' });
|
hasuraToast({ type: 'success', title: 'Reload successful!' });
|
||||||
invalidateMetadata();
|
|
||||||
},
|
},
|
||||||
onError: () => {
|
onError: () => {
|
||||||
hasuraToast({ type: 'error', title: 'Failed to reload source.' });
|
hasuraToast({ type: 'error', title: 'Failed to reload source.' });
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import React, { useEffect, useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { InjectedRouter, Link, withRouter } from 'react-router';
|
import { InjectedRouter, Link, withRouter } from 'react-router';
|
||||||
import { useDestructiveAlert } from '../../../../new-components/Alert';
|
import { useDestructiveAlert } from '../../../../new-components/Alert';
|
||||||
import { Button } from '../../../../new-components/Button';
|
import { Button } from '../../../../new-components/Button';
|
||||||
@ -8,22 +8,20 @@ import {
|
|||||||
useEnvironmentState,
|
useEnvironmentState,
|
||||||
usePushRoute,
|
usePushRoute,
|
||||||
} from '../../../ConnectDBRedesign/hooks';
|
} from '../../../ConnectDBRedesign/hooks';
|
||||||
import {
|
import { useMetadata } from '../../../hasura-metadata-api';
|
||||||
useInvalidateMetadata,
|
|
||||||
useMetadata,
|
|
||||||
} from '../../../hasura-metadata-api';
|
|
||||||
import { useTrackLogicalModel } from '../../hooks/useTrackLogicalModel';
|
import { useTrackLogicalModel } from '../../hooks/useTrackLogicalModel';
|
||||||
import { useTrackNativeQuery } from '../../hooks/useTrackNativeQuery';
|
import { useTrackNativeQuery } from '../../hooks/useTrackNativeQuery';
|
||||||
import { LogicalModelWidget } from '../LogicalModelWidget/LogicalModelWidget';
|
import { LogicalModelWidget } from '../LogicalModelWidget/LogicalModelWidget';
|
||||||
|
|
||||||
|
import { LimitedFeatureWrapper } from '../../../ConnectDBRedesign/components/LimitedFeatureWrapper/LimitedFeatureWrapper';
|
||||||
|
import { extractModelsAndQueriesFromMetadata } from '../../../hasura-metadata-api/selectors';
|
||||||
|
import { useSyncResourceVersionOnMount } from '../../../hasura-metadata-api';
|
||||||
|
import { RouteWrapper } from '../components/RouteWrapper';
|
||||||
|
import { NATIVE_QUERY_ROUTES } from '../constants';
|
||||||
import { LogicalModelWithSource, NativeQueryWithSource } from '../types';
|
import { LogicalModelWithSource, NativeQueryWithSource } from '../types';
|
||||||
import { ListLogicalModels } from './components/ListLogicalModels';
|
import { ListLogicalModels } from './components/ListLogicalModels';
|
||||||
import { ListNativeQueries } from './components/ListNativeQueries';
|
import { ListNativeQueries } from './components/ListNativeQueries';
|
||||||
import { ListStoredProcedures } from './components/ListStoredProcedures';
|
import { ListStoredProcedures } from './components/ListStoredProcedures';
|
||||||
import { NATIVE_QUERY_ROUTES } from '../constants';
|
|
||||||
import { extractModelsAndQueriesFromMetadata } from '../../../hasura-metadata-api/selectors';
|
|
||||||
import { RouteWrapper } from '../components/RouteWrapper';
|
|
||||||
import { LimitedFeatureWrapper } from '../../../ConnectDBRedesign/components/LimitedFeatureWrapper/LimitedFeatureWrapper';
|
|
||||||
|
|
||||||
export const LandingPage = ({ pathname }: { pathname: string }) => {
|
export const LandingPage = ({ pathname }: { pathname: string }) => {
|
||||||
const push = usePushRoute();
|
const push = usePushRoute();
|
||||||
@ -41,15 +39,7 @@ export const LandingPage = ({ pathname }: { pathname: string }) => {
|
|||||||
.flat()
|
.flat()
|
||||||
);
|
);
|
||||||
|
|
||||||
const invalidateMetadata = useInvalidateMetadata();
|
useSyncResourceVersionOnMount({ componentName: 'LandingPage' });
|
||||||
useEffect(() => {
|
|
||||||
/**
|
|
||||||
* Workaround to avoid that a metadata migration that happened in the legacy part of the Console (i.e. Run SQL)
|
|
||||||
* might affect the metadata migrations in the child components of this page,
|
|
||||||
* resulting in the error "metadata resource version referenced (x) did not match current version"
|
|
||||||
*/
|
|
||||||
invalidateMetadata();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const nativeQueries = data?.queries ?? [];
|
const nativeQueries = data?.queries ?? [];
|
||||||
const logicalModels = data?.models ?? [];
|
const logicalModels = data?.models ?? [];
|
||||||
|
@ -1,13 +1,11 @@
|
|||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import { useMetadataMigration } from '../../../../MetadataAPI';
|
|
||||||
import { exportMetadata } from '../../../../DataSource';
|
|
||||||
import { useHttpClient } from '../../../../Network';
|
|
||||||
import { getCreateLogicalModelBody } from './utils/getCreateLogicalModelBody';
|
|
||||||
import { LogicalModel, Source } from '../../../../hasura-metadata-types';
|
|
||||||
import { useQueryClient } from 'react-query';
|
|
||||||
import { useFireNotification } from '../../../../../new-components/Notifications/index';
|
import { useFireNotification } from '../../../../../new-components/Notifications/index';
|
||||||
import { METADATA_QUERY_KEY } from '../../../../hasura-metadata-api/useMetadata';
|
import { exportMetadata } from '../../../../DataSource';
|
||||||
|
import { useMetadataMigration } from '../../../../MetadataAPI';
|
||||||
|
import { useHttpClient } from '../../../../Network';
|
||||||
|
import { LogicalModel, Source } from '../../../../hasura-metadata-types';
|
||||||
import { errorTransform } from './utils/errorTransform';
|
import { errorTransform } from './utils/errorTransform';
|
||||||
|
import { getCreateLogicalModelBody } from './utils/getCreateLogicalModelBody';
|
||||||
|
|
||||||
const useCreateLogicalModelsPermissions = ({
|
const useCreateLogicalModelsPermissions = ({
|
||||||
logicalModels,
|
logicalModels,
|
||||||
@ -21,7 +19,6 @@ const useCreateLogicalModelsPermissions = ({
|
|||||||
});
|
});
|
||||||
const { fireNotification } = useFireNotification();
|
const { fireNotification } = useFireNotification();
|
||||||
const httpClient = useHttpClient();
|
const httpClient = useHttpClient();
|
||||||
const queryClient = useQueryClient();
|
|
||||||
|
|
||||||
const create = useCallback(
|
const create = useCallback(
|
||||||
async ({ permission, logicalModelName, onSuccess }) => {
|
async ({ permission, logicalModelName, onSuccess }) => {
|
||||||
@ -60,7 +57,6 @@ const useCreateLogicalModelsPermissions = ({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
onSettled: async () => {
|
onSettled: async () => {
|
||||||
await queryClient.invalidateQueries([METADATA_QUERY_KEY]);
|
|
||||||
onSuccess?.();
|
onSuccess?.();
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,11 @@
|
|||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import { useMetadataMigration } from '../../../../MetadataAPI';
|
import { useFireNotification } from '../../../../../new-components/Notifications/index';
|
||||||
import { exportMetadata } from '../../../../DataSource';
|
import { exportMetadata } from '../../../../DataSource';
|
||||||
|
import { useMetadataMigration } from '../../../../MetadataAPI';
|
||||||
import { useHttpClient } from '../../../../Network';
|
import { useHttpClient } from '../../../../Network';
|
||||||
import { LogicalModel, Source } from '../../../../hasura-metadata-types';
|
import { LogicalModel, Source } from '../../../../hasura-metadata-types';
|
||||||
import { useQueryClient } from 'react-query';
|
|
||||||
import { useFireNotification } from '../../../../../new-components/Notifications/index';
|
|
||||||
import { METADATA_QUERY_KEY } from '../../../../hasura-metadata-api/useMetadata';
|
|
||||||
import { errorTransform } from './utils/errorTransform';
|
|
||||||
import { Permission } from '../components/types';
|
import { Permission } from '../components/types';
|
||||||
|
import { errorTransform } from './utils/errorTransform';
|
||||||
import { getDeleteLogicalModelBody } from './utils/getDeleteLogicalModelBody';
|
import { getDeleteLogicalModelBody } from './utils/getDeleteLogicalModelBody';
|
||||||
|
|
||||||
const useRemoveLogicalModelsPermissions = ({
|
const useRemoveLogicalModelsPermissions = ({
|
||||||
@ -22,7 +20,6 @@ const useRemoveLogicalModelsPermissions = ({
|
|||||||
});
|
});
|
||||||
const { fireNotification } = useFireNotification();
|
const { fireNotification } = useFireNotification();
|
||||||
const httpClient = useHttpClient();
|
const httpClient = useHttpClient();
|
||||||
const queryClient = useQueryClient();
|
|
||||||
|
|
||||||
const remove = useCallback(
|
const remove = useCallback(
|
||||||
async ({
|
async ({
|
||||||
@ -68,7 +65,6 @@ const useRemoveLogicalModelsPermissions = ({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
onSettled: async () => {
|
onSettled: async () => {
|
||||||
await queryClient.invalidateQueries([METADATA_QUERY_KEY]);
|
|
||||||
onSuccess?.();
|
onSuccess?.();
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,13 @@
|
|||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import {
|
|
||||||
useInvalidateMetadata,
|
|
||||||
useMetadata,
|
|
||||||
} from '../../../hasura-metadata-api';
|
|
||||||
import { Table } from '../../../hasura-metadata-types';
|
|
||||||
import { useMetadataMigration } from '../../../MetadataAPI';
|
import { useMetadataMigration } from '../../../MetadataAPI';
|
||||||
|
import { useMetadata } from '../../../hasura-metadata-api';
|
||||||
|
import { Table } from '../../../hasura-metadata-types';
|
||||||
|
|
||||||
export const useUntrackTable = (props?: {
|
export const useUntrackTable = (props?: {
|
||||||
onSuccess?: () => void;
|
onSuccess?: () => void;
|
||||||
onError?: (err: Error) => void;
|
onError?: (err: Error) => void;
|
||||||
}) => {
|
}) => {
|
||||||
const { mutate, ...rest } = useMetadataMigration();
|
const { mutate, ...rest } = useMetadataMigration();
|
||||||
const invalidateMetadata = useInvalidateMetadata();
|
|
||||||
|
|
||||||
const { onSuccess, onError } = props ?? {};
|
const { onSuccess, onError } = props ?? {};
|
||||||
|
|
||||||
@ -37,7 +33,6 @@ export const useUntrackTable = (props?: {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
invalidateMetadata();
|
|
||||||
onSuccess?.();
|
onSuccess?.();
|
||||||
},
|
},
|
||||||
onError: err => {
|
onError: err => {
|
||||||
|
@ -1,12 +1,8 @@
|
|||||||
import {
|
|
||||||
MetadataUtils,
|
|
||||||
useInvalidateMetadata,
|
|
||||||
useMetadata,
|
|
||||||
} from '../../../hasura-metadata-api';
|
|
||||||
import { MetadataTable } from '../../../hasura-metadata-types';
|
|
||||||
import { useMetadataMigration } from '../../../MetadataAPI';
|
|
||||||
import { useFireNotification } from '../../../../new-components/Notifications';
|
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
|
import { useFireNotification } from '../../../../new-components/Notifications';
|
||||||
|
import { useMetadataMigration } from '../../../MetadataAPI';
|
||||||
|
import { MetadataUtils, useMetadata } from '../../../hasura-metadata-api';
|
||||||
|
import { MetadataTable } from '../../../hasura-metadata-types';
|
||||||
|
|
||||||
export const useUpdateTableConfiguration = (
|
export const useUpdateTableConfiguration = (
|
||||||
dataSourceName: string,
|
dataSourceName: string,
|
||||||
@ -16,8 +12,6 @@ export const useUpdateTableConfiguration = (
|
|||||||
|
|
||||||
const { fireNotification } = useFireNotification();
|
const { fireNotification } = useFireNotification();
|
||||||
|
|
||||||
const invalidateMetadata = useInvalidateMetadata();
|
|
||||||
|
|
||||||
const { data } = useMetadata(m => ({
|
const { data } = useMetadata(m => ({
|
||||||
source: MetadataUtils.findMetadataSource(dataSourceName, m),
|
source: MetadataUtils.findMetadataSource(dataSourceName, m),
|
||||||
resource_version: m.resource_version,
|
resource_version: m.resource_version,
|
||||||
@ -52,8 +46,6 @@ export const useUpdateTableConfiguration = (
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
invalidateMetadata();
|
|
||||||
|
|
||||||
fireNotification({
|
fireNotification({
|
||||||
type: 'success',
|
type: 'success',
|
||||||
title: 'Success!',
|
title: 'Success!',
|
||||||
@ -77,7 +69,6 @@ export const useUpdateTableConfiguration = (
|
|||||||
dataSourceName,
|
dataSourceName,
|
||||||
fireNotification,
|
fireNotification,
|
||||||
mutate,
|
mutate,
|
||||||
invalidateMetadata,
|
|
||||||
metadataTable,
|
metadataTable,
|
||||||
resource_version,
|
resource_version,
|
||||||
source,
|
source,
|
||||||
|
@ -118,7 +118,14 @@ export const TrackedFunctions = (props: TrackedFunctionsProps) => {
|
|||||||
[
|
[
|
||||||
<span
|
<span
|
||||||
className="py-2"
|
className="py-2"
|
||||||
onClick={() => invalidateMetadata()}
|
onClick={() =>
|
||||||
|
invalidateMetadata({
|
||||||
|
componentName: 'TrackedFunctions',
|
||||||
|
reasons: [
|
||||||
|
'Refreshing tracked functions on dropdown menu item click.',
|
||||||
|
],
|
||||||
|
})
|
||||||
|
}
|
||||||
>
|
>
|
||||||
Refresh
|
Refresh
|
||||||
</span>,
|
</span>,
|
||||||
|
@ -163,7 +163,14 @@ export const UntrackedFunctions = (props: UntrackedFunctionsProps) => {
|
|||||||
[
|
[
|
||||||
<span
|
<span
|
||||||
className="py-2"
|
className="py-2"
|
||||||
onClick={() => invalidateMetadata()}
|
onClick={() =>
|
||||||
|
invalidateMetadata({
|
||||||
|
componentName: 'UntrackedFunctions',
|
||||||
|
reasons: [
|
||||||
|
'Refreshing untracked functions on Dropdown Menu item click.',
|
||||||
|
],
|
||||||
|
})
|
||||||
|
}
|
||||||
>
|
>
|
||||||
Refresh
|
Refresh
|
||||||
</span>,
|
</span>,
|
||||||
|
@ -1,38 +1,35 @@
|
|||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
|
import { FaAngleLeft, FaAngleRight } from 'react-icons/fa';
|
||||||
|
import Skeleton from 'react-loading-skeleton';
|
||||||
|
import { APIError } from '../../../../hooks/error';
|
||||||
|
import { Badge } from '../../../../new-components/Badge';
|
||||||
import { Button } from '../../../../new-components/Button';
|
import { Button } from '../../../../new-components/Button';
|
||||||
import { CardedTable } from '../../../../new-components/CardedTable';
|
import { CardedTable } from '../../../../new-components/CardedTable';
|
||||||
|
import { IndicatorCard } from '../../../../new-components/IndicatorCard';
|
||||||
|
import { useFireNotification } from '../../../../new-components/Notifications';
|
||||||
|
import { hasuraToast } from '../../../../new-components/Toasts';
|
||||||
|
import { exportMetadata } from '../../../DataSource';
|
||||||
|
import { RelationshipMapping } from '../../../DatabaseRelationships/components/AvailableRelationshipsList/parts/RelationshipMapping';
|
||||||
|
import { RowActions } from '../../../DatabaseRelationships/components/AvailableRelationshipsList/parts/RowActions';
|
||||||
|
import { TargetName } from '../../../DatabaseRelationships/components/AvailableRelationshipsList/parts/TargetName';
|
||||||
|
import { RenderWidget } from '../../../DatabaseRelationships/components/RenderWidget/RenderWidget';
|
||||||
|
import { NOTIFICATIONS } from '../../../DatabaseRelationships/components/constants';
|
||||||
|
import { useCheckRows } from '../../../DatabaseRelationships/hooks/useCheckRows';
|
||||||
|
import { MODE, Relationship } from '../../../DatabaseRelationships/types';
|
||||||
|
import {
|
||||||
|
generateDeleteLocalRelationshipRequest,
|
||||||
|
generateRemoteRelationshipDeleteRequest,
|
||||||
|
} from '../../../DatabaseRelationships/utils/generateRequest';
|
||||||
|
import { useMetadataMigration } from '../../../MetadataAPI';
|
||||||
|
import { useHttpClient } from '../../../Network';
|
||||||
|
import { BulkKeepGoingResponse, Source } from '../../../hasura-metadata-types';
|
||||||
import {
|
import {
|
||||||
DEFAULT_PAGE_NUMBER,
|
DEFAULT_PAGE_NUMBER,
|
||||||
DEFAULT_PAGE_SIZE,
|
DEFAULT_PAGE_SIZE,
|
||||||
DEFAULT_PAGE_SIZES,
|
DEFAULT_PAGE_SIZES,
|
||||||
} from '../constants';
|
} from '../constants';
|
||||||
import { FaAngleLeft, FaAngleRight } from 'react-icons/fa';
|
|
||||||
import { paginate } from '../utils';
|
import { paginate } from '../utils';
|
||||||
import { SearchBar } from './SearchBar';
|
import { SearchBar } from './SearchBar';
|
||||||
import { Badge } from '../../../../new-components/Badge';
|
|
||||||
import { hasuraToast } from '../../../../new-components/Toasts';
|
|
||||||
import { TargetName } from '../../../DatabaseRelationships/components/AvailableRelationshipsList/parts/TargetName';
|
|
||||||
import { RelationshipMapping } from '../../../DatabaseRelationships/components/AvailableRelationshipsList/parts/RelationshipMapping';
|
|
||||||
import { RowActions } from '../../../DatabaseRelationships/components/AvailableRelationshipsList/parts/RowActions';
|
|
||||||
import { MODE, Relationship } from '../../../DatabaseRelationships/types';
|
|
||||||
import { RenderWidget } from '../../../DatabaseRelationships/components/RenderWidget/RenderWidget';
|
|
||||||
import { NOTIFICATIONS } from '../../../DatabaseRelationships/components/constants';
|
|
||||||
import { useFireNotification } from '../../../../new-components/Notifications';
|
|
||||||
import { useMetadataMigration } from '../../../MetadataAPI';
|
|
||||||
import {
|
|
||||||
generateDeleteLocalRelationshipRequest,
|
|
||||||
generateRemoteRelationshipDeleteRequest,
|
|
||||||
} from '../../../DatabaseRelationships/utils/generateRequest';
|
|
||||||
import { exportMetadata } from '../../../DataSource';
|
|
||||||
import { useHttpClient } from '../../../Network';
|
|
||||||
import { IndicatorCard } from '../../../../new-components/IndicatorCard';
|
|
||||||
import { MetadataDataSource } from '../../../../metadata/types';
|
|
||||||
import Skeleton from 'react-loading-skeleton';
|
|
||||||
import { generateQueryKeys } from '../../../DatabaseRelationships/utils/queryClientUtils';
|
|
||||||
import { useQueryClient } from 'react-query';
|
|
||||||
import { useCheckRows } from '../../../DatabaseRelationships/hooks/useCheckRows';
|
|
||||||
import { APIError } from '../../../../hooks/error';
|
|
||||||
import { BulkKeepGoingResponse } from '../../../hasura-metadata-types';
|
|
||||||
|
|
||||||
const getQueryFunction = (relationship: Relationship) => {
|
const getQueryFunction = (relationship: Relationship) => {
|
||||||
if (relationship.type === 'localRelationship') {
|
if (relationship.type === 'localRelationship') {
|
||||||
@ -58,7 +55,7 @@ type RelationshipAction = {
|
|||||||
|
|
||||||
interface TrackedRelationshipsProps {
|
interface TrackedRelationshipsProps {
|
||||||
dataSourceName: string;
|
dataSourceName: string;
|
||||||
driver?: MetadataDataSource['kind'];
|
driver?: Source['kind'];
|
||||||
isLoading: boolean;
|
isLoading: boolean;
|
||||||
onUpdate: () => void;
|
onUpdate: () => void;
|
||||||
relationships: Relationship[];
|
relationships: Relationship[];
|
||||||
@ -73,7 +70,6 @@ export const TrackedRelationships: React.VFC<TrackedRelationshipsProps> = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const httpClient = useHttpClient();
|
const httpClient = useHttpClient();
|
||||||
const { mutateAsync } = useMetadataMigration<BulkKeepGoingResponse>();
|
const { mutateAsync } = useMetadataMigration<BulkKeepGoingResponse>();
|
||||||
const queryClient = useQueryClient();
|
|
||||||
|
|
||||||
const [isTrackingSelectedRelationships, setTrackingSelectedRelationships] =
|
const [isTrackingSelectedRelationships, setTrackingSelectedRelationships] =
|
||||||
useState(false);
|
useState(false);
|
||||||
@ -161,6 +157,8 @@ export const TrackedRelationships: React.VFC<TrackedRelationshipsProps> = ({
|
|||||||
).length;
|
).length;
|
||||||
const plural = successfullyTrackedCounter > 1 ? 's' : '';
|
const plural = successfullyTrackedCounter > 1 ? 's' : '';
|
||||||
|
|
||||||
|
onUpdate();
|
||||||
|
|
||||||
hasuraToast({
|
hasuraToast({
|
||||||
type: 'success',
|
type: 'success',
|
||||||
title: 'Successfully untracked',
|
title: 'Successfully untracked',
|
||||||
@ -174,13 +172,8 @@ export const TrackedRelationships: React.VFC<TrackedRelationshipsProps> = ({
|
|||||||
message: (err as APIError).message,
|
message: (err as APIError).message,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
onSettled: () => {
|
|
||||||
queryClient.invalidateQueries(generateQueryKeys.metadata());
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
onUpdate();
|
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
|
@ -1,18 +1,12 @@
|
|||||||
import React, { useEffect } from 'react';
|
import React from 'react';
|
||||||
import { useTrackedRelationships } from './hooks/useTrackedRelationships';
|
|
||||||
import { useInvalidateMetadata } from '../../../hasura-metadata-api';
|
import {
|
||||||
import { useMetadata } from '../../../MetadataAPI';
|
MetadataSelectors,
|
||||||
|
useMetadata,
|
||||||
|
useSyncResourceVersionOnMount,
|
||||||
|
} from '../../../hasura-metadata-api';
|
||||||
import { TrackedRelationships } from './TrackedRelationships';
|
import { TrackedRelationships } from './TrackedRelationships';
|
||||||
|
import { useTrackedRelationships } from './hooks/useTrackedRelationships';
|
||||||
const useInvalidateMetadataOnLoad = () => {
|
|
||||||
const invalidateMetadata = useInvalidateMetadata();
|
|
||||||
|
|
||||||
// just invalidate metadata when this screen loads for the first time
|
|
||||||
// why? because the user might be coming from a redux based paged and the resource_version might gone out of sync
|
|
||||||
useEffect(() => {
|
|
||||||
invalidateMetadata();
|
|
||||||
}, [invalidateMetadata]);
|
|
||||||
};
|
|
||||||
|
|
||||||
interface TrackedRelationshipsContainerProps {
|
interface TrackedRelationshipsContainerProps {
|
||||||
dataSourceName: string;
|
dataSourceName: string;
|
||||||
@ -21,7 +15,9 @@ interface TrackedRelationshipsContainerProps {
|
|||||||
export const TrackedRelationshipsContainer: React.VFC<
|
export const TrackedRelationshipsContainer: React.VFC<
|
||||||
TrackedRelationshipsContainerProps
|
TrackedRelationshipsContainerProps
|
||||||
> = ({ dataSourceName }) => {
|
> = ({ dataSourceName }) => {
|
||||||
useInvalidateMetadataOnLoad();
|
useSyncResourceVersionOnMount({
|
||||||
|
componentName: 'TrackedRelationshipsContainer',
|
||||||
|
});
|
||||||
|
|
||||||
const {
|
const {
|
||||||
data: relationships,
|
data: relationships,
|
||||||
@ -29,18 +25,9 @@ export const TrackedRelationshipsContainer: React.VFC<
|
|||||||
refetchRelationships,
|
refetchRelationships,
|
||||||
} = useTrackedRelationships(dataSourceName);
|
} = useTrackedRelationships(dataSourceName);
|
||||||
|
|
||||||
const {
|
const { data: metadataSource, isLoading: isLoadingMetadata } = useMetadata(
|
||||||
data: metadataDataSource,
|
MetadataSelectors.findSource(dataSourceName)
|
||||||
refetch: refetchMetadata,
|
);
|
||||||
isLoading: isLoadingMetadata,
|
|
||||||
} = useMetadata(m => {
|
|
||||||
return {
|
|
||||||
resource_version: m.resource_version,
|
|
||||||
source: m.metadata.sources.find(s => s.name === dataSourceName),
|
|
||||||
};
|
|
||||||
});
|
|
||||||
const metadataSource = metadataDataSource?.source;
|
|
||||||
const driver = metadataSource?.kind;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TrackedRelationships
|
<TrackedRelationships
|
||||||
@ -49,9 +36,8 @@ export const TrackedRelationshipsContainer: React.VFC<
|
|||||||
relationships={relationships}
|
relationships={relationships}
|
||||||
onUpdate={async () => {
|
onUpdate={async () => {
|
||||||
await refetchRelationships();
|
await refetchRelationships();
|
||||||
await refetchMetadata();
|
|
||||||
}}
|
}}
|
||||||
driver={driver}
|
driver={metadataSource?.kind}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
import { useQuery } from 'react-query';
|
import { useQuery } from 'react-query';
|
||||||
import { useAllSuggestedRelationships } from '../../../../DatabaseRelationships/components/SuggestedRelationships/hooks/useAllSuggestedRelationships';
|
import { useAllSuggestedRelationships } from '../../../../DatabaseRelationships/components/SuggestedRelationships/hooks/useAllSuggestedRelationships';
|
||||||
import { getTableLocalRelationships } from '../../../../DatabaseRelationships/utils/tableRelationships';
|
import { getTableLocalRelationships } from '../../../../DatabaseRelationships/utils/tableRelationships';
|
||||||
import { exportMetadata } from '../../../../hasura-metadata-api';
|
import {
|
||||||
import { useHttpClient } from '../../../../Network';
|
MetadataSelectors,
|
||||||
|
useMetadata,
|
||||||
|
} from '../../../../hasura-metadata-api';
|
||||||
|
|
||||||
export const getTrackedRelationshipsCacheKey = (dataSourceName: string) => [
|
export const getTrackedRelationshipsCacheKey = (dataSourceName: string) => [
|
||||||
'tracked_relationships',
|
'tracked_relationships',
|
||||||
@ -10,21 +12,16 @@ export const getTrackedRelationshipsCacheKey = (dataSourceName: string) => [
|
|||||||
];
|
];
|
||||||
|
|
||||||
export const useTrackedRelationships = (dataSourceName: string) => {
|
export const useTrackedRelationships = (dataSourceName: string) => {
|
||||||
const httpClient = useHttpClient();
|
|
||||||
const { suggestedRelationships } = useAllSuggestedRelationships({
|
const { suggestedRelationships } = useAllSuggestedRelationships({
|
||||||
dataSourceName,
|
dataSourceName,
|
||||||
isEnabled: true,
|
isEnabled: true,
|
||||||
omitTracked: false,
|
omitTracked: false,
|
||||||
});
|
});
|
||||||
|
const { data: currentMetadataSource } = useMetadata(
|
||||||
const fetchLocalRelationships = async () => {
|
MetadataSelectors.findSource(dataSourceName)
|
||||||
const { metadata } = await exportMetadata({
|
|
||||||
httpClient,
|
|
||||||
});
|
|
||||||
const currentMetadataSource = metadata?.sources?.find(
|
|
||||||
source => source.name === dataSourceName
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const fetchLocalRelationships = async () => {
|
||||||
const metadataTables = currentMetadataSource?.tables || [];
|
const metadataTables = currentMetadataSource?.tables || [];
|
||||||
|
|
||||||
const _tableRelationships = [];
|
const _tableRelationships = [];
|
||||||
|
@ -1,3 +1,2 @@
|
|||||||
export { useCheckRows } from './useCheckRows';
|
export { useCheckRows } from './useCheckRows';
|
||||||
export { useMetadataSource } from './useMetadataSource';
|
|
||||||
export { usePaginatedSearchableList } from './usePaginatedSearchableList';
|
export { usePaginatedSearchableList } from './usePaginatedSearchableList';
|
||||||
|
@ -1,24 +0,0 @@
|
|||||||
import { exportMetadata } from '../../../DataSource';
|
|
||||||
import { useHttpClient } from '../../../Network';
|
|
||||||
import { useQuery } from 'react-query';
|
|
||||||
|
|
||||||
export const useMetadataSource = (dataSourceName: string) => {
|
|
||||||
const httpClient = useHttpClient();
|
|
||||||
return useQuery(
|
|
||||||
['export_metadata', 'trackTables', 'metadataSource'],
|
|
||||||
async () => {
|
|
||||||
const result = await exportMetadata({ httpClient });
|
|
||||||
|
|
||||||
if (!result) throw Error('useMetadataSource: cannot export metadata');
|
|
||||||
|
|
||||||
const driver = result.metadata.sources.find(
|
|
||||||
source => source.name === dataSourceName
|
|
||||||
)?.kind;
|
|
||||||
|
|
||||||
if (!driver)
|
|
||||||
throw Error('useMetadataSource: cannot find source in metadata');
|
|
||||||
|
|
||||||
return { metadata: result, driver };
|
|
||||||
}
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,8 +1,4 @@
|
|||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import {
|
|
||||||
MetadataFunction,
|
|
||||||
QualifiedFunction,
|
|
||||||
} from '../../hasura-metadata-types';
|
|
||||||
import {
|
import {
|
||||||
MetadataMigrationOptions,
|
MetadataMigrationOptions,
|
||||||
useMetadataMigration,
|
useMetadataMigration,
|
||||||
@ -10,9 +6,12 @@ import {
|
|||||||
import {
|
import {
|
||||||
MetadataSelectors,
|
MetadataSelectors,
|
||||||
areTablesEqual,
|
areTablesEqual,
|
||||||
useInvalidateMetadata,
|
|
||||||
useMetadata,
|
useMetadata,
|
||||||
} from '../../hasura-metadata-api';
|
} from '../../hasura-metadata-api';
|
||||||
|
import {
|
||||||
|
MetadataFunction,
|
||||||
|
QualifiedFunction,
|
||||||
|
} from '../../hasura-metadata-types';
|
||||||
import { transformErrorResponse } from '../errorUtils';
|
import { transformErrorResponse } from '../errorUtils';
|
||||||
|
|
||||||
export type MetadataFunctionPayload = {
|
export type MetadataFunctionPayload = {
|
||||||
@ -26,12 +25,9 @@ export const useSetFunctionConfiguration = ({
|
|||||||
dataSourceName,
|
dataSourceName,
|
||||||
...globalMutateOptions
|
...globalMutateOptions
|
||||||
}: { dataSourceName: string } & MetadataMigrationOptions) => {
|
}: { dataSourceName: string } & MetadataMigrationOptions) => {
|
||||||
const invalidateMetadata = useInvalidateMetadata();
|
|
||||||
|
|
||||||
const { mutate, ...rest } = useMetadataMigration({
|
const { mutate, ...rest } = useMetadataMigration({
|
||||||
...globalMutateOptions,
|
...globalMutateOptions,
|
||||||
onSuccess: (data, variables, ctx) => {
|
onSuccess: (data, variables, ctx) => {
|
||||||
invalidateMetadata();
|
|
||||||
globalMutateOptions?.onSuccess?.(data, variables, ctx);
|
globalMutateOptions?.onSuccess?.(data, variables, ctx);
|
||||||
},
|
},
|
||||||
errorTransform: transformErrorResponse,
|
errorTransform: transformErrorResponse,
|
||||||
|
@ -1,17 +1,13 @@
|
|||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import {
|
|
||||||
MetadataFunction,
|
|
||||||
QualifiedFunction,
|
|
||||||
} from '../../hasura-metadata-types';
|
|
||||||
import {
|
import {
|
||||||
MetadataMigrationOptions,
|
MetadataMigrationOptions,
|
||||||
useMetadataMigration,
|
useMetadataMigration,
|
||||||
} from '../../MetadataAPI/hooks/useMetadataMigration';
|
} from '../../MetadataAPI/hooks/useMetadataMigration';
|
||||||
|
import { MetadataSelectors, useMetadata } from '../../hasura-metadata-api';
|
||||||
import {
|
import {
|
||||||
MetadataSelectors,
|
MetadataFunction,
|
||||||
useInvalidateMetadata,
|
QualifiedFunction,
|
||||||
useMetadata,
|
} from '../../hasura-metadata-types';
|
||||||
} from '../../hasura-metadata-api';
|
|
||||||
import { transformErrorResponse } from '../errorUtils';
|
import { transformErrorResponse } from '../errorUtils';
|
||||||
|
|
||||||
export type MetadataFunctionPayload = {
|
export type MetadataFunctionPayload = {
|
||||||
@ -25,12 +21,9 @@ export const useTrackFunction = ({
|
|||||||
dataSourceName,
|
dataSourceName,
|
||||||
...globalMutateOptions
|
...globalMutateOptions
|
||||||
}: { dataSourceName: string } & MetadataMigrationOptions) => {
|
}: { dataSourceName: string } & MetadataMigrationOptions) => {
|
||||||
const invalidateMetadata = useInvalidateMetadata();
|
|
||||||
|
|
||||||
const { mutate, ...rest } = useMetadataMigration({
|
const { mutate, ...rest } = useMetadataMigration({
|
||||||
...globalMutateOptions,
|
...globalMutateOptions,
|
||||||
onSuccess: (data, variables, ctx) => {
|
onSuccess: (data, variables, ctx) => {
|
||||||
invalidateMetadata();
|
|
||||||
globalMutateOptions?.onSuccess?.(data, variables, ctx);
|
globalMutateOptions?.onSuccess?.(data, variables, ctx);
|
||||||
},
|
},
|
||||||
errorTransform: transformErrorResponse,
|
errorTransform: transformErrorResponse,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { transformErrorResponse } from '../../ConnectDBRedesign/utils';
|
import { transformErrorResponse } from '../../ConnectDBRedesign/utils';
|
||||||
import { useMetadataMigration } from '../../MetadataAPI';
|
import { useMetadataMigration } from '../../MetadataAPI';
|
||||||
import { MetadataMigrationOptions } from '../../MetadataAPI/hooks/useMetadataMigration';
|
import { MetadataMigrationOptions } from '../../MetadataAPI/hooks/useMetadataMigration';
|
||||||
import { useInvalidateMetadata, useMetadata } from '../../hasura-metadata-api';
|
import { useMetadata } from '../../hasura-metadata-api';
|
||||||
import { LogicalModel } from '../../hasura-metadata-types';
|
import { LogicalModel } from '../../hasura-metadata-types';
|
||||||
import { getSourceDriver } from './utils';
|
import { getSourceDriver } from './utils';
|
||||||
|
|
||||||
@ -20,13 +20,10 @@ export const useTrackLogicalModel = (
|
|||||||
resource_version: m.resource_version,
|
resource_version: m.resource_version,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const invalidateMetadata = useInvalidateMetadata();
|
|
||||||
|
|
||||||
const { mutate, ...rest } = useMetadataMigration({
|
const { mutate, ...rest } = useMetadataMigration({
|
||||||
...globalMutateOptions,
|
...globalMutateOptions,
|
||||||
errorTransform: transformErrorResponse,
|
errorTransform: transformErrorResponse,
|
||||||
onSuccess: (data, variable, ctx) => {
|
onSuccess: (data, variable, ctx) => {
|
||||||
invalidateMetadata();
|
|
||||||
globalMutateOptions?.onSuccess?.(data, variable, ctx);
|
globalMutateOptions?.onSuccess?.(data, variable, ctx);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { transformErrorResponse } from '../../ConnectDBRedesign/utils';
|
import { transformErrorResponse } from '../../ConnectDBRedesign/utils';
|
||||||
import { useMetadataMigration } from '../../MetadataAPI';
|
import { useMetadataMigration } from '../../MetadataAPI';
|
||||||
import { MetadataMigrationOptions } from '../../MetadataAPI/hooks/useMetadataMigration';
|
import { MetadataMigrationOptions } from '../../MetadataAPI/hooks/useMetadataMigration';
|
||||||
import { useInvalidateMetadata, useMetadata } from '../../hasura-metadata-api';
|
import { useMetadata } from '../../hasura-metadata-api';
|
||||||
import { NativeQuery, Source } from '../../hasura-metadata-types';
|
import { NativeQuery, Source } from '../../hasura-metadata-types';
|
||||||
import { getSourceDriver } from './utils';
|
import { getSourceDriver } from './utils';
|
||||||
|
|
||||||
@ -25,13 +25,10 @@ export const useTrackNativeQuery = (
|
|||||||
resource_version: m.resource_version,
|
resource_version: m.resource_version,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const invalidateMetadata = useInvalidateMetadata();
|
|
||||||
|
|
||||||
const { mutate, ...rest } = useMetadataMigration({
|
const { mutate, ...rest } = useMetadataMigration({
|
||||||
...globalMutateOptions,
|
...globalMutateOptions,
|
||||||
errorTransform: transformErrorResponse,
|
errorTransform: transformErrorResponse,
|
||||||
onSuccess: (data, variable, ctx) => {
|
onSuccess: (data, variable, ctx) => {
|
||||||
invalidateMetadata();
|
|
||||||
globalMutateOptions?.onSuccess?.(data, variable, ctx);
|
globalMutateOptions?.onSuccess?.(data, variable, ctx);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { transformErrorResponse } from '../../ConnectDBRedesign/utils';
|
import { transformErrorResponse } from '../../ConnectDBRedesign/utils';
|
||||||
import { useMetadataMigration } from '../../MetadataAPI';
|
import { useMetadataMigration } from '../../MetadataAPI';
|
||||||
import { MetadataMigrationOptions } from '../../MetadataAPI/hooks/useMetadataMigration';
|
import { MetadataMigrationOptions } from '../../MetadataAPI/hooks/useMetadataMigration';
|
||||||
import { useInvalidateMetadata, useMetadata } from '../../hasura-metadata-api';
|
import { useMetadata } from '../../hasura-metadata-api';
|
||||||
import {
|
import {
|
||||||
QualifiedStoredProcedure,
|
QualifiedStoredProcedure,
|
||||||
StoredProcedure,
|
StoredProcedure,
|
||||||
@ -23,13 +23,10 @@ export const useTrackStoredProcedure = (
|
|||||||
resource_version: m.resource_version,
|
resource_version: m.resource_version,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const invalidateMetadata = useInvalidateMetadata();
|
|
||||||
|
|
||||||
const { mutate, ...rest } = useMetadataMigration({
|
const { mutate, ...rest } = useMetadataMigration({
|
||||||
...globalMutateOptions,
|
...globalMutateOptions,
|
||||||
errorTransform: transformErrorResponse,
|
errorTransform: transformErrorResponse,
|
||||||
onSuccess: (data, variable, ctx) => {
|
onSuccess: (data, variable, ctx) => {
|
||||||
invalidateMetadata();
|
|
||||||
globalMutateOptions?.onSuccess?.(data, variable, ctx);
|
globalMutateOptions?.onSuccess?.(data, variable, ctx);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -1,14 +1,10 @@
|
|||||||
import { useMetadataMigration } from '../../MetadataAPI';
|
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import {
|
|
||||||
MetadataSelectors,
|
|
||||||
useInvalidateMetadata,
|
|
||||||
useMetadata,
|
|
||||||
} from '../../hasura-metadata-api';
|
|
||||||
import type { TrackableTable } from '../TrackResources/types';
|
|
||||||
import { MetadataMigrationOptions } from '../../MetadataAPI/hooks/useMetadataMigration';
|
|
||||||
import { transformErrorResponse } from '../../ConnectDBRedesign/utils';
|
import { transformErrorResponse } from '../../ConnectDBRedesign/utils';
|
||||||
|
import { useMetadataMigration } from '../../MetadataAPI';
|
||||||
|
import { MetadataMigrationOptions } from '../../MetadataAPI/hooks/useMetadataMigration';
|
||||||
|
import { MetadataSelectors, useMetadata } from '../../hasura-metadata-api';
|
||||||
import { BulkKeepGoingResponse } from '../../hasura-metadata-types';
|
import { BulkKeepGoingResponse } from '../../hasura-metadata-types';
|
||||||
|
import type { TrackableTable } from '../TrackResources/types';
|
||||||
|
|
||||||
export const useTrackTables = ({
|
export const useTrackTables = ({
|
||||||
dataSourceName,
|
dataSourceName,
|
||||||
@ -19,12 +15,9 @@ export const useTrackTables = ({
|
|||||||
resource_version: m.resource_version,
|
resource_version: m.resource_version,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const invalidateMetadata = useInvalidateMetadata();
|
|
||||||
|
|
||||||
const { mutate, ...rest } = useMetadataMigration<BulkKeepGoingResponse>({
|
const { mutate, ...rest } = useMetadataMigration<BulkKeepGoingResponse>({
|
||||||
...globalMutateOptions,
|
...globalMutateOptions,
|
||||||
onSuccess: (data, variables, ctx) => {
|
onSuccess: (data, variables, ctx) => {
|
||||||
invalidateMetadata();
|
|
||||||
globalMutateOptions?.onSuccess?.(data, variables, ctx);
|
globalMutateOptions?.onSuccess?.(data, variables, ctx);
|
||||||
},
|
},
|
||||||
errorTransform: transformErrorResponse,
|
errorTransform: transformErrorResponse,
|
||||||
|
@ -2,7 +2,6 @@ export * from './ManageDatabase/ManageDatabase.Route';
|
|||||||
export * from './components';
|
export * from './components';
|
||||||
export * from './hooks';
|
export * from './hooks';
|
||||||
export { useTrackTables } from './hooks/useTrackTables';
|
export { useTrackTables } from './hooks/useTrackTables';
|
||||||
export { useMetadataSource } from './TrackResources/hooks/useMetadataSource';
|
|
||||||
export * from './CustomFieldNames';
|
export * from './CustomFieldNames';
|
||||||
export * from '../../utils/getDataRoute';
|
export * from '../../utils/getDataRoute';
|
||||||
export * from './mocks/metadata.mocks';
|
export * from './mocks/metadata.mocks';
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
import { useState, useEffect } from 'react';
|
import { useState } from 'react';
|
||||||
import { Table } from '../hasura-metadata-types';
|
import { FaPlusCircle } from 'react-icons/fa';
|
||||||
import { Button } from '../../new-components/Button';
|
import { Button } from '../../new-components/Button';
|
||||||
import { useFireNotification } from '../../new-components/Notifications';
|
import { useFireNotification } from '../../new-components/Notifications';
|
||||||
import { FaPlusCircle } from 'react-icons/fa';
|
import { useSyncResourceVersionOnMount } from '../hasura-metadata-api';
|
||||||
import Legend from './components/Legend';
|
import { Table } from '../hasura-metadata-types';
|
||||||
import { SuggestedRelationships } from './components/SuggestedRelationships/SuggestedRelationships';
|
|
||||||
import { MODE, Relationship } from './types';
|
|
||||||
import { AvailableRelationshipsList } from './components/AvailableRelationshipsList/AvailableRelationshipsList';
|
import { AvailableRelationshipsList } from './components/AvailableRelationshipsList/AvailableRelationshipsList';
|
||||||
import { NOTIFICATIONS } from './components/constants';
|
import Legend from './components/Legend';
|
||||||
import { RenderWidget } from './components/RenderWidget/RenderWidget';
|
import { RenderWidget } from './components/RenderWidget/RenderWidget';
|
||||||
import { useInvalidateMetadata } from '../hasura-metadata-api';
|
import { SuggestedRelationships } from './components/SuggestedRelationships/SuggestedRelationships';
|
||||||
|
import { NOTIFICATIONS } from './components/constants';
|
||||||
|
import { MODE, Relationship } from './types';
|
||||||
|
|
||||||
export interface DatabaseRelationshipsProps {
|
export interface DatabaseRelationshipsProps {
|
||||||
dataSourceName: string;
|
dataSourceName: string;
|
||||||
@ -29,8 +29,6 @@ export const DatabaseRelationships = ({
|
|||||||
});
|
});
|
||||||
const { fireNotification } = useFireNotification();
|
const { fireNotification } = useFireNotification();
|
||||||
|
|
||||||
const invalidateMetadata = useInvalidateMetadata();
|
|
||||||
|
|
||||||
const onCancel = () => {
|
const onCancel = () => {
|
||||||
setTabState({
|
setTabState({
|
||||||
mode: undefined,
|
mode: undefined,
|
||||||
@ -38,11 +36,9 @@ export const DatabaseRelationships = ({
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// just invalidate metadata when this screen loads for the first time
|
useSyncResourceVersionOnMount({
|
||||||
// why? because the user might be coming from a redux based paged and the resource_version might gone out of sync
|
componentName: 'DatabaseRelationships',
|
||||||
useEffect(() => {
|
});
|
||||||
invalidateMetadata();
|
|
||||||
}, [invalidateMetadata]);
|
|
||||||
|
|
||||||
const onError = (err: Error) => {
|
const onError = (err: Error) => {
|
||||||
if (mode)
|
if (mode)
|
||||||
|
@ -1,13 +1,11 @@
|
|||||||
import React from 'react';
|
|
||||||
import { Table } from '../../../hasura-metadata-types';
|
|
||||||
import { CardedTable } from '../../../../new-components/CardedTable';
|
|
||||||
import { IndicatorCard } from '../../../../new-components/IndicatorCard';
|
|
||||||
import { FiRefreshCcw } from 'react-icons/fi';
|
import { FiRefreshCcw } from 'react-icons/fi';
|
||||||
import Skeleton from 'react-loading-skeleton';
|
import Skeleton from 'react-loading-skeleton';
|
||||||
import { QueryClient, useQueryClient } from 'react-query';
|
import { CardedTable } from '../../../../new-components/CardedTable';
|
||||||
|
import { IndicatorCard } from '../../../../new-components/IndicatorCard';
|
||||||
|
import { useInvalidateMetadata } from '../../../hasura-metadata-api';
|
||||||
|
import { Table } from '../../../hasura-metadata-types';
|
||||||
import { useListAllDatabaseRelationships } from '../../hooks/useListAllDatabaseRelationships';
|
import { useListAllDatabaseRelationships } from '../../hooks/useListAllDatabaseRelationships';
|
||||||
import { MODE, Relationship } from '../../types';
|
import { MODE, Relationship } from '../../types';
|
||||||
import { generateQueryKeys } from '../../utils/queryClientUtils';
|
|
||||||
import { RelationshipMapping } from './parts/RelationshipMapping';
|
import { RelationshipMapping } from './parts/RelationshipMapping';
|
||||||
import { RowActions } from './parts/RowActions';
|
import { RowActions } from './parts/RowActions';
|
||||||
import { TargetName } from './parts/TargetName';
|
import { TargetName } from './parts/TargetName';
|
||||||
@ -18,10 +16,6 @@ export interface AvailableRelationshipsListProps {
|
|||||||
table: Table;
|
table: Table;
|
||||||
}
|
}
|
||||||
|
|
||||||
const refreshMetadata = (client: QueryClient) => {
|
|
||||||
client.invalidateQueries(generateQueryKeys.metadata());
|
|
||||||
};
|
|
||||||
|
|
||||||
export const AvailableRelationshipsList = ({
|
export const AvailableRelationshipsList = ({
|
||||||
dataSourceName,
|
dataSourceName,
|
||||||
onAction,
|
onAction,
|
||||||
@ -32,7 +26,14 @@ export const AvailableRelationshipsList = ({
|
|||||||
table,
|
table,
|
||||||
});
|
});
|
||||||
|
|
||||||
const queryClient = useQueryClient();
|
const invalidateMetadata = useInvalidateMetadata();
|
||||||
|
|
||||||
|
const refreshMetadata = () => {
|
||||||
|
invalidateMetadata({
|
||||||
|
componentName: 'AvailableRelationshipList',
|
||||||
|
reasons: ['User clicked button to refresh metadata.'],
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
if (!relationships) return <Skeleton count={7} height={30} />;
|
if (!relationships) return <Skeleton count={7} height={30} />;
|
||||||
|
|
||||||
@ -55,7 +56,7 @@ export const AvailableRelationshipsList = ({
|
|||||||
'TYPE',
|
'TYPE',
|
||||||
'RELATIONSHIP',
|
'RELATIONSHIP',
|
||||||
<div className="flex justify-end hidden">
|
<div className="flex justify-end hidden">
|
||||||
<FiRefreshCcw onClick={() => refreshMetadata(queryClient)} />
|
<FiRefreshCcw onClick={() => refreshMetadata()} />
|
||||||
</div>,
|
</div>,
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
@ -5,19 +5,12 @@ import { transformErrorResponse } from '../../../Data/errorUtils';
|
|||||||
// useAllDriverCapabilities,
|
// useAllDriverCapabilities,
|
||||||
// useDriverCapabilities,
|
// useDriverCapabilities,
|
||||||
// } from '../../../Data/hooks/useDriverCapabilities';
|
// } from '../../../Data/hooks/useDriverCapabilities';
|
||||||
|
import { useAllDriverCapabilities } from '../../../Data/hooks/useAllDriverCapabilities';
|
||||||
import { Feature } from '../../../DataSource';
|
import { Feature } from '../../../DataSource';
|
||||||
import { useMetadataMigration } from '../../../MetadataAPI';
|
import { useMetadataMigration } from '../../../MetadataAPI';
|
||||||
import { MetadataMigrationOptions } from '../../../MetadataAPI/hooks/useMetadataMigration';
|
import { MetadataMigrationOptions } from '../../../MetadataAPI/hooks/useMetadataMigration';
|
||||||
import {
|
import { areTablesEqual, useMetadata } from '../../../hasura-metadata-api';
|
||||||
areTablesEqual,
|
import { Table } from '../../../hasura-metadata-types';
|
||||||
useInvalidateMetadata,
|
|
||||||
useMetadata,
|
|
||||||
} from '../../../hasura-metadata-api';
|
|
||||||
import {
|
|
||||||
createTableRelationshipRequestBody,
|
|
||||||
deleteTableRelationshipRequestBody,
|
|
||||||
renameRelationshipRequestBody,
|
|
||||||
} from './utils';
|
|
||||||
import {
|
import {
|
||||||
DeleteRelationshipProps,
|
DeleteRelationshipProps,
|
||||||
LocalTableRelationshipDefinition,
|
LocalTableRelationshipDefinition,
|
||||||
@ -26,8 +19,11 @@ import {
|
|||||||
RenameRelationshipProps,
|
RenameRelationshipProps,
|
||||||
TableRelationshipBasicDetails,
|
TableRelationshipBasicDetails,
|
||||||
} from './types';
|
} from './types';
|
||||||
import { Table } from '../../../hasura-metadata-types';
|
import {
|
||||||
import { useAllDriverCapabilities } from '../../../Data/hooks/useAllDriverCapabilities';
|
createTableRelationshipRequestBody,
|
||||||
|
deleteTableRelationshipRequestBody,
|
||||||
|
renameRelationshipRequestBody,
|
||||||
|
} from './utils';
|
||||||
|
|
||||||
type AllowedRelationshipDefinitions =
|
type AllowedRelationshipDefinitions =
|
||||||
| Omit<LocalTableRelationshipDefinition, 'capabilities'>
|
| Omit<LocalTableRelationshipDefinition, 'capabilities'>
|
||||||
@ -66,8 +62,6 @@ export const useCreateTableRelationships = (
|
|||||||
dataSourceName: string,
|
dataSourceName: string,
|
||||||
globalMutateOptions?: MetadataMigrationOptions
|
globalMutateOptions?: MetadataMigrationOptions
|
||||||
) => {
|
) => {
|
||||||
const invalidateMetadata = useInvalidateMetadata();
|
|
||||||
|
|
||||||
// get these capabilities
|
// get these capabilities
|
||||||
|
|
||||||
const { data: driverCapabilties = [] } = useAllDriverCapabilities({
|
const { data: driverCapabilties = [] } = useAllDriverCapabilities({
|
||||||
@ -152,7 +146,6 @@ export const useCreateTableRelationships = (
|
|||||||
...globalMutateOptions,
|
...globalMutateOptions,
|
||||||
errorTransform: transformErrorResponse,
|
errorTransform: transformErrorResponse,
|
||||||
onSuccess: (data, variable, ctx) => {
|
onSuccess: (data, variable, ctx) => {
|
||||||
invalidateMetadata();
|
|
||||||
globalMutateOptions?.onSuccess?.(data, variable, ctx);
|
globalMutateOptions?.onSuccess?.(data, variable, ctx);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -34,8 +34,6 @@ export const useManageLocalRelationship = ({
|
|||||||
const mutationOptions = useMemo(
|
const mutationOptions = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
queryClient.invalidateQueries(generateQueryKeys.metadata());
|
|
||||||
|
|
||||||
queryClient.invalidateQueries(
|
queryClient.invalidateQueries(
|
||||||
generateQueryKeys.suggestedRelationships({ dataSourceName, table })
|
generateQueryKeys.suggestedRelationships({ dataSourceName, table })
|
||||||
);
|
);
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
import { useMetadataMigration } from '../../MetadataAPI';
|
|
||||||
import { useCallback, useMemo } from 'react';
|
import { useCallback, useMemo } from 'react';
|
||||||
import { useQueryClient } from 'react-query';
|
import { useQueryClient } from 'react-query';
|
||||||
|
import { useMetadataMigration } from '../../MetadataAPI';
|
||||||
import { useMetadata } from '../../hasura-metadata-api';
|
import { useMetadata } from '../../hasura-metadata-api';
|
||||||
import { RemoteDatabaseRelationship } from '../types';
|
import { RemoteDatabaseRelationship } from '../types';
|
||||||
import {
|
import {
|
||||||
generateRemoteRelationshipCreateRequest,
|
generateRemoteRelationshipCreateRequest,
|
||||||
generateRemoteRelationshipEditRequest,
|
|
||||||
generateRemoteRelationshipDeleteRequest,
|
generateRemoteRelationshipDeleteRequest,
|
||||||
|
generateRemoteRelationshipEditRequest,
|
||||||
} from '../utils/generateRequest';
|
} from '../utils/generateRequest';
|
||||||
import { generateQueryKeys } from '../utils/queryClientUtils';
|
|
||||||
|
|
||||||
export const useManageRemoteDatabaseRelationship = ({
|
export const useManageRemoteDatabaseRelationship = ({
|
||||||
dataSourceName,
|
dataSourceName,
|
||||||
@ -31,7 +30,6 @@ export const useManageRemoteDatabaseRelationship = ({
|
|||||||
const mutationOptions = useMemo(
|
const mutationOptions = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
queryClient.invalidateQueries(generateQueryKeys.metadata());
|
|
||||||
onSuccess?.();
|
onSuccess?.();
|
||||||
},
|
},
|
||||||
onError: (err: Error) => {
|
onError: (err: Error) => {
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
import { useMetadataMigration } from '../../MetadataAPI';
|
|
||||||
import { useCallback, useMemo } from 'react';
|
import { useCallback, useMemo } from 'react';
|
||||||
import { useQueryClient } from 'react-query';
|
import { useQueryClient } from 'react-query';
|
||||||
|
import { useMetadataMigration } from '../../MetadataAPI';
|
||||||
import { useMetadata } from '../../hasura-metadata-api';
|
import { useMetadata } from '../../hasura-metadata-api';
|
||||||
import { RemoteSchemaRelationship } from '../types';
|
import { RemoteSchemaRelationship } from '../types';
|
||||||
import {
|
import {
|
||||||
generateRemoteRelationshipCreateRequest,
|
generateRemoteRelationshipCreateRequest,
|
||||||
generateRemoteRelationshipEditRequest,
|
|
||||||
generateRemoteRelationshipDeleteRequest,
|
generateRemoteRelationshipDeleteRequest,
|
||||||
|
generateRemoteRelationshipEditRequest,
|
||||||
} from '../utils/generateRequest';
|
} from '../utils/generateRequest';
|
||||||
import { generateQueryKeys } from '../utils/queryClientUtils';
|
|
||||||
|
|
||||||
export const useManageRemoteSchemaRelationship = ({
|
export const useManageRemoteSchemaRelationship = ({
|
||||||
dataSourceName,
|
dataSourceName,
|
||||||
@ -31,7 +30,6 @@ export const useManageRemoteSchemaRelationship = ({
|
|||||||
const mutationOptions = useMemo(
|
const mutationOptions = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
queryClient.invalidateQueries(generateQueryKeys.metadata());
|
|
||||||
onSuccess?.();
|
onSuccess?.();
|
||||||
},
|
},
|
||||||
onError: (err: Error) => {
|
onError: (err: Error) => {
|
||||||
|
@ -11,7 +11,6 @@ interface ManyTablesParams {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const generateQueryKeys = {
|
export const generateQueryKeys = {
|
||||||
metadata: () => ['export_metadata'],
|
|
||||||
fkConstraints: (params: BaseParams) =>
|
fkConstraints: (params: BaseParams) =>
|
||||||
[
|
[
|
||||||
'dal-introspection',
|
'dal-introspection',
|
||||||
|
@ -3,12 +3,34 @@ import { Api } from '../../../hooks/apiUtils';
|
|||||||
import { useQuery, UseQueryOptions, UseQueryResult } from 'react-query';
|
import { useQuery, UseQueryOptions, UseQueryResult } from 'react-query';
|
||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
import type { MetadataResponse } from '../types';
|
import type { MetadataResponse } from '../types';
|
||||||
|
import {
|
||||||
|
METADATA_QUERY_KEY,
|
||||||
|
MetadataQueryKey,
|
||||||
|
} from '../../hasura-metadata-api/useMetadata';
|
||||||
|
|
||||||
// overloads
|
// overloads
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @deprecated
|
||||||
|
* this metadata library function is no longer recommended.
|
||||||
|
* Please use the `useMetadata` from the features/hasura-metadata-api
|
||||||
|
*/
|
||||||
export function useMetadata(): UseQueryResult<MetadataResponse, Error>;
|
export function useMetadata(): UseQueryResult<MetadataResponse, Error>;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @deprecated
|
||||||
|
* this metadta library function is no longer recommended.
|
||||||
|
* Please use the `useMetadata` from the features/hasura-metadata-api
|
||||||
|
*/
|
||||||
export function useMetadata<T extends (d: MetadataResponse) => any>(
|
export function useMetadata<T extends (d: MetadataResponse) => any>(
|
||||||
select: T
|
select: T
|
||||||
): UseQueryResult<ReturnType<T>, Error>;
|
): UseQueryResult<ReturnType<T>, Error>;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @deprecated
|
||||||
|
* this metadta library function is no longer recommended.
|
||||||
|
* Please use the `useMetadata` from the features/hasura-metadata-api
|
||||||
|
*/
|
||||||
export function useMetadata<
|
export function useMetadata<
|
||||||
T extends (d: MetadataResponse) => any,
|
T extends (d: MetadataResponse) => any,
|
||||||
D extends (d: ReturnType<T>) => any
|
D extends (d: ReturnType<T>) => any
|
||||||
@ -16,16 +38,21 @@ export function useMetadata<
|
|||||||
select: T,
|
select: T,
|
||||||
transformFn: D,
|
transformFn: D,
|
||||||
queryOptions?: Omit<
|
queryOptions?: Omit<
|
||||||
UseQueryOptions<MetadataResponse, Error, ReturnType<T>, 'metadata'>,
|
UseQueryOptions<MetadataResponse, Error, ReturnType<T>, MetadataQueryKey>,
|
||||||
'queryKey' | 'queryFn'
|
'queryKey' | 'queryFn'
|
||||||
>
|
>
|
||||||
): UseQueryResult<ReturnType<D>, Error>;
|
): UseQueryResult<ReturnType<D>, Error>;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @deprecated
|
||||||
|
* this metadta library function is no longer recommended.
|
||||||
|
* Please use the `useMetadata` from the features/hasura-metadata-api
|
||||||
|
*/
|
||||||
export function useMetadata(
|
export function useMetadata(
|
||||||
select = (d: MetadataResponse) => d,
|
select = (d: MetadataResponse) => d,
|
||||||
transformFn = (d: unknown) => d,
|
transformFn = (d: unknown) => d,
|
||||||
queryOptions?: Omit<
|
queryOptions?: Omit<
|
||||||
UseQueryOptions<MetadataResponse, Error, unknown, 'metadata'>,
|
UseQueryOptions<MetadataResponse, Error, unknown, MetadataQueryKey>,
|
||||||
'queryKey' | 'queryFn'
|
'queryKey' | 'queryFn'
|
||||||
>
|
>
|
||||||
) {
|
) {
|
||||||
@ -49,7 +76,7 @@ export function useMetadata(
|
|||||||
};
|
};
|
||||||
|
|
||||||
return useQuery({
|
return useQuery({
|
||||||
queryKey: 'metadata',
|
queryKey: METADATA_QUERY_KEY,
|
||||||
queryFn,
|
queryFn,
|
||||||
...queryOptions,
|
...queryOptions,
|
||||||
select: d => transformFn(select(d)),
|
select: d => transformFn(select(d)),
|
||||||
|
@ -5,6 +5,7 @@ import Endpoints from '../../../Endpoints';
|
|||||||
import { Api } from '../../../hooks/apiUtils';
|
import { Api } from '../../../hooks/apiUtils';
|
||||||
import { useConsoleConfig } from '../../../hooks/useEnvVars';
|
import { useConsoleConfig } from '../../../hooks/useEnvVars';
|
||||||
import { allowedMetadataTypes, MetadataResponse } from '../types';
|
import { allowedMetadataTypes, MetadataResponse } from '../types';
|
||||||
|
import { useInvalidateMetadata } from '../../hasura-metadata-api';
|
||||||
|
|
||||||
const maxAllowedLength = 255;
|
const maxAllowedLength = 255;
|
||||||
const unixEpochLength = 14;
|
const unixEpochLength = 14;
|
||||||
@ -46,7 +47,8 @@ export function useMetadataMigration<
|
|||||||
metadataMigrationOptions: MetadataMigrationOptions<
|
metadataMigrationOptions: MetadataMigrationOptions<
|
||||||
ResponseType,
|
ResponseType,
|
||||||
ArgsType
|
ArgsType
|
||||||
> = {}
|
> = {},
|
||||||
|
additionalQueryKeysToInvalidate?: string[]
|
||||||
) {
|
) {
|
||||||
const { errorTransform, ...mutationOptions } = metadataMigrationOptions;
|
const { errorTransform, ...mutationOptions } = metadataMigrationOptions;
|
||||||
|
|
||||||
@ -57,11 +59,14 @@ export function useMetadataMigration<
|
|||||||
string
|
string
|
||||||
>;
|
>;
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
|
const invalidateMetadata = useInvalidateMetadata();
|
||||||
|
let lastBody: any = null;
|
||||||
|
|
||||||
return useMutation(
|
return useMutation(
|
||||||
async props => {
|
async props => {
|
||||||
const { query } = props;
|
const { query } = props;
|
||||||
const body = query;
|
const body = query;
|
||||||
|
lastBody = body;
|
||||||
const result = await Api.post<ResponseType>(
|
const result = await Api.post<ResponseType>(
|
||||||
{
|
{
|
||||||
url: Endpoints.metadata,
|
url: Endpoints.metadata,
|
||||||
@ -94,10 +99,20 @@ export function useMetadataMigration<
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
invalidateMetadata({
|
||||||
Get the latest metadata from server (this will NOT update metadata that is in the redux state, to do that please pass a custom onSuccess)
|
componentName: 'useMetadataMigration()',
|
||||||
*/
|
reasons: [
|
||||||
queryClient.refetchQueries(['metadata'], { active: true });
|
'Metadata migration occurred',
|
||||||
|
`Migration Type: ${lastBody.type}`,
|
||||||
|
`Migration Body:`,
|
||||||
|
JSON.stringify(lastBody, null, 2),
|
||||||
|
],
|
||||||
|
additionalQueryKeys:
|
||||||
|
additionalQueryKeysToInvalidate &&
|
||||||
|
additionalQueryKeysToInvalidate?.length > 0
|
||||||
|
? additionalQueryKeysToInvalidate
|
||||||
|
: undefined,
|
||||||
|
});
|
||||||
|
|
||||||
const { onSuccess } = mutationOptions ?? {};
|
const { onSuccess } = mutationOptions ?? {};
|
||||||
if (onSuccess) {
|
if (onSuccess) {
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
import type { SetOpenTelemetryQuery } from '../../../hasura-metadata-types';
|
import type { SetOpenTelemetryQuery } from '../../../hasura-metadata-types';
|
||||||
|
|
||||||
import { useMetadataVersion, useMetadataMigration } from '../../../MetadataAPI';
|
import { useMetadataMigration, useMetadataVersion } from '../../../MetadataAPI';
|
||||||
|
|
||||||
import { useFireNotification } from '../../../../new-components/Notifications';
|
import { useFireNotification } from '../../../../new-components/Notifications';
|
||||||
import { useInvalidateMetadata } from '../../../hasura-metadata-api';
|
|
||||||
|
|
||||||
import type { FormValues } from '../../OpenTelemetry/components/Form/schema';
|
import type { FormValues } from '../../OpenTelemetry/components/Form/schema';
|
||||||
|
|
||||||
@ -22,7 +21,6 @@ function errorTransform(error: unknown) {
|
|||||||
export function useSetOpenTelemetry() {
|
export function useSetOpenTelemetry() {
|
||||||
const mutation = useMetadataMigration({ errorTransform });
|
const mutation = useMetadataMigration({ errorTransform });
|
||||||
const { data: version } = useMetadataVersion();
|
const { data: version } = useMetadataVersion();
|
||||||
const invalidateMetadata = useInvalidateMetadata();
|
|
||||||
|
|
||||||
const { fireNotification } = useFireNotification();
|
const { fireNotification } = useFireNotification();
|
||||||
|
|
||||||
@ -45,7 +43,6 @@ export function useSetOpenTelemetry() {
|
|||||||
{
|
{
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
resolve();
|
resolve();
|
||||||
invalidateMetadata();
|
|
||||||
|
|
||||||
fireNotification({
|
fireNotification({
|
||||||
title: 'Success!',
|
title: 'Success!',
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
import { useQueryClient } from 'react-query';
|
|
||||||
import { AxiosInstance } from 'axios';
|
import { AxiosInstance } from 'axios';
|
||||||
|
import { useQueryClient } from 'react-query';
|
||||||
|
|
||||||
import { useMetadataMigration } from '../../../../MetadataAPI';
|
|
||||||
import { exportMetadata } from '../../../../DataSource';
|
|
||||||
import { useHttpClient } from '../../../../Network';
|
|
||||||
import { useFireNotification } from '../../../../../new-components/Notifications';
|
import { useFireNotification } from '../../../../../new-components/Notifications';
|
||||||
import { AccessType, QueryType } from '../../../types';
|
import { exportMetadata } from '../../../../DataSource';
|
||||||
import { api } from '../../api';
|
import { useMetadataMigration } from '../../../../MetadataAPI';
|
||||||
import { isPermission, keyToPermission } from '../../../utils';
|
import { useHttpClient } from '../../../../Network';
|
||||||
import { PermissionsSchema } from '../../../schema';
|
|
||||||
import { Table } from '../../../../hasura-metadata-types';
|
import { Table } from '../../../../hasura-metadata-types';
|
||||||
|
import { PermissionsSchema } from '../../../schema';
|
||||||
|
import { AccessType, QueryType } from '../../../types';
|
||||||
|
import { isPermission, keyToPermission } from '../../../utils';
|
||||||
|
import { api } from '../../api';
|
||||||
|
|
||||||
export interface UseSubmitFormArgs {
|
export interface UseSubmitFormArgs {
|
||||||
dataSourceName: string;
|
dataSourceName: string;
|
||||||
@ -68,11 +68,12 @@ export const useSubmitForm = (args: UseSubmitFormArgs) => {
|
|||||||
args;
|
args;
|
||||||
|
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
const httpClient = useHttpClient();
|
const httpClient = useHttpClient();
|
||||||
|
|
||||||
const { fireNotification } = useFireNotification();
|
const { fireNotification } = useFireNotification();
|
||||||
|
|
||||||
const mutate = useMetadataMigration();
|
const mutate = useMetadataMigration(undefined, ['roles']);
|
||||||
|
|
||||||
const submit = async (formData: PermissionsSchema) => {
|
const submit = async (formData: PermissionsSchema) => {
|
||||||
const { metadata, resource_version } = await exportMetadata({
|
const { metadata, resource_version } = await exportMetadata({
|
||||||
@ -129,7 +130,6 @@ export const useSubmitForm = (args: UseSubmitFormArgs) => {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
onSettled: () => {
|
onSettled: () => {
|
||||||
queryClient.invalidateQueries(['export_metadata', 'roles']);
|
|
||||||
queryClient.invalidateQueries([
|
queryClient.invalidateQueries([
|
||||||
dataSourceName,
|
dataSourceName,
|
||||||
'permissionFormData',
|
'permissionFormData',
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
|
import { useMutation } from 'react-query';
|
||||||
import Endpoints from '../../../../Endpoints';
|
import Endpoints from '../../../../Endpoints';
|
||||||
import { Api } from '../../../../hooks/apiUtils';
|
import { Api } from '../../../../hooks/apiUtils';
|
||||||
import { useAppSelector } from '../../../../storeHooks';
|
import { useAppSelector } from '../../../../storeHooks';
|
||||||
import { useMutation, useQueryClient } from 'react-query';
|
import { useInvalidateMetadata } from '../../../hasura-metadata-api';
|
||||||
|
|
||||||
export const useAddRemoteSchemaRelationship = () => {
|
export const useAddRemoteSchemaRelationship = () => {
|
||||||
const queryClient = useQueryClient();
|
const invalidateMetadata = useInvalidateMetadata();
|
||||||
const headers = useAppSelector(state => state.tables.dataHeaders);
|
const headers = useAppSelector(state => state.tables.dataHeaders);
|
||||||
|
|
||||||
return useMutation(
|
return useMutation(
|
||||||
@ -19,13 +20,16 @@ export const useAddRemoteSchemaRelationship = () => {
|
|||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
queryClient.refetchQueries(['metadata'], { active: true });
|
invalidateMetadata({
|
||||||
|
componentName: 'useAddRemoteSchemaRelationship',
|
||||||
|
reasons: ['added a remote schema relationship'],
|
||||||
|
});
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
export const useDropRemoteSchemaRelationship = () => {
|
export const useDropRemoteSchemaRelationship = () => {
|
||||||
const queryClient = useQueryClient();
|
const invalidateMetadata = useInvalidateMetadata();
|
||||||
const headers = useAppSelector(state => state.tables.dataHeaders);
|
const headers = useAppSelector(state => state.tables.dataHeaders);
|
||||||
|
|
||||||
return useMutation(
|
return useMutation(
|
||||||
@ -40,7 +44,10 @@ export const useDropRemoteSchemaRelationship = () => {
|
|||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
queryClient.refetchQueries(['metadata'], { active: true });
|
invalidateMetadata({
|
||||||
|
componentName: 'useDropRemoteSchemaRelationship',
|
||||||
|
reasons: ['dropped a remote schema relationship'],
|
||||||
|
});
|
||||||
},
|
},
|
||||||
onError: () => {},
|
onError: () => {},
|
||||||
}
|
}
|
||||||
@ -48,7 +55,7 @@ export const useDropRemoteSchemaRelationship = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const useUpdateRemoteSchemaRelationship = () => {
|
export const useUpdateRemoteSchemaRelationship = () => {
|
||||||
const queryClient = useQueryClient();
|
const invalidateMetadata = useInvalidateMetadata();
|
||||||
const headers = useAppSelector(state => state.tables.dataHeaders);
|
const headers = useAppSelector(state => state.tables.dataHeaders);
|
||||||
|
|
||||||
return useMutation(
|
return useMutation(
|
||||||
@ -63,7 +70,10 @@ export const useUpdateRemoteSchemaRelationship = () => {
|
|||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
queryClient.refetchQueries(['metadata'], { active: true });
|
invalidateMetadata({
|
||||||
|
componentName: 'useUpdateRemoteSchemaRelationship',
|
||||||
|
reasons: ['updated a remote schema relationship'],
|
||||||
|
});
|
||||||
},
|
},
|
||||||
onError: () => {},
|
onError: () => {},
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,10 @@ export {
|
|||||||
useInconsistentMetadata,
|
useInconsistentMetadata,
|
||||||
useInvalidateInconsistentMetadata,
|
useInvalidateInconsistentMetadata,
|
||||||
} from './useInconsistentMetadata';
|
} from './useInconsistentMetadata';
|
||||||
export { useMetadata, useInvalidateMetadata } from './useMetadata';
|
export { useMetadata } from './useMetadata';
|
||||||
|
export type { MetadataQueryKey } from './useMetadata';
|
||||||
|
export { useInvalidateMetadata } from './useInvalidateMetadata';
|
||||||
|
export { useSyncResourceVersionOnMount } from './useSyncResourceVersionOnMount';
|
||||||
export { areTablesEqual } from './areTablesEqual';
|
export { areTablesEqual } from './areTablesEqual';
|
||||||
export { MetadataSelectors };
|
export { MetadataSelectors };
|
||||||
export { MetadataUtils };
|
export { MetadataUtils };
|
||||||
|
@ -0,0 +1,16 @@
|
|||||||
|
import { Metadata } from '../hasura-metadata-types';
|
||||||
|
import { reactQueryClient } from '../../lib/reactQuery';
|
||||||
|
import { METADATA_QUERY_KEY } from './useMetadata';
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* You only want to use these in helper libraries, and not in React Components.
|
||||||
|
*
|
||||||
|
* NEVER use these in React Components as it could produce unexpected results.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
export const MetadataHelpers = {
|
||||||
|
getQueryData: () =>
|
||||||
|
reactQueryClient.getQueryData<Metadata>(METADATA_QUERY_KEY),
|
||||||
|
invalidate: () => reactQueryClient.invalidateQueries(METADATA_QUERY_KEY),
|
||||||
|
};
|
@ -0,0 +1,40 @@
|
|||||||
|
import { useCallback } from 'react';
|
||||||
|
import { useQueryClient } from 'react-query';
|
||||||
|
import globals from '../../Globals';
|
||||||
|
import { METADATA_QUERY_KEY } from './useMetadata';
|
||||||
|
|
||||||
|
export type LogMetadataInvalidationProps = {
|
||||||
|
componentName: string;
|
||||||
|
reasons: string[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export const logMetadataInvalidation = ({
|
||||||
|
componentName,
|
||||||
|
reasons,
|
||||||
|
}: LogMetadataInvalidationProps) => {
|
||||||
|
if (!globals.isProduction) {
|
||||||
|
const logLabel = 'Invalidating Metadata...';
|
||||||
|
console.groupCollapsed(logLabel);
|
||||||
|
console.info(`Component: ${componentName}`);
|
||||||
|
console.info(`Reasons:`);
|
||||||
|
reasons.forEach(reason => console.info(`\t${reason}`));
|
||||||
|
console.groupEnd();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useInvalidateMetadata = () => {
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
const invalidate = useCallback(
|
||||||
|
(
|
||||||
|
props: LogMetadataInvalidationProps & { additionalQueryKeys?: string[] }
|
||||||
|
) => {
|
||||||
|
logMetadataInvalidation(props);
|
||||||
|
queryClient.invalidateQueries([
|
||||||
|
METADATA_QUERY_KEY,
|
||||||
|
...(props?.additionalQueryKeys ?? []),
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
[queryClient]
|
||||||
|
);
|
||||||
|
return invalidate;
|
||||||
|
};
|
@ -1,10 +1,10 @@
|
|||||||
import { exportMetadata } from './exportMetadata';
|
import { useQuery } from 'react-query';
|
||||||
import { Metadata } from '../hasura-metadata-types';
|
|
||||||
import { useHttpClient } from '../Network';
|
|
||||||
import { useCallback } from 'react';
|
|
||||||
import { useQuery, useQueryClient } from 'react-query';
|
|
||||||
import { APIError } from '../../hooks/error';
|
import { APIError } from '../../hooks/error';
|
||||||
import { useAppDispatch } from '../../storeHooks';
|
import { useAppDispatch } from '../../storeHooks';
|
||||||
|
import { useHttpClient } from '../Network';
|
||||||
|
import { Metadata } from '../hasura-metadata-types';
|
||||||
|
import { exportMetadata } from './exportMetadata';
|
||||||
|
import { getCurrentReduxResourceVersion } from '../../store/utils/';
|
||||||
|
|
||||||
export const DEFAULT_STALE_TIME = 5 * 60000; // 5 minutes as default stale time
|
export const DEFAULT_STALE_TIME = 5 * 60000; // 5 minutes as default stale time
|
||||||
|
|
||||||
@ -14,17 +14,9 @@ export const DEFAULT_STALE_TIME = 5 * 60000; // 5 minutes as default stale time
|
|||||||
Default stale time is 5 minutes, but can be adjusted using the staleTime arg
|
Default stale time is 5 minutes, but can be adjusted using the staleTime arg
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export const METADATA_QUERY_KEY = 'export_metadata';
|
export type MetadataQueryKey = 'export_metadata';
|
||||||
|
|
||||||
export const useInvalidateMetadata = () => {
|
export const METADATA_QUERY_KEY: MetadataQueryKey = 'export_metadata';
|
||||||
const queryClient = useQueryClient();
|
|
||||||
const invalidate = useCallback(
|
|
||||||
() => queryClient.invalidateQueries([METADATA_QUERY_KEY]),
|
|
||||||
[queryClient]
|
|
||||||
);
|
|
||||||
|
|
||||||
return invalidate;
|
|
||||||
};
|
|
||||||
|
|
||||||
type Options = {
|
type Options = {
|
||||||
staleTime?: number;
|
staleTime?: number;
|
||||||
@ -39,7 +31,7 @@ export const useMetadata = <FinalResult = Metadata>(
|
|||||||
}
|
}
|
||||||
) => {
|
) => {
|
||||||
const httpClient = useHttpClient();
|
const httpClient = useHttpClient();
|
||||||
const invalidateMetadata = useInvalidateMetadata();
|
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
const queryReturn = useQuery<Metadata, APIError, FinalResult>({
|
const queryReturn = useQuery<Metadata, APIError, FinalResult>({
|
||||||
@ -47,10 +39,12 @@ export const useMetadata = <FinalResult = Metadata>(
|
|||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
const result = await exportMetadata({ httpClient });
|
const result = await exportMetadata({ httpClient });
|
||||||
|
|
||||||
|
if (result.resource_version !== getCurrentReduxResourceVersion()) {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'Metadata/EXPORT_METADATA_SUCCESS',
|
type: 'Metadata/EXPORT_METADATA_SUCCESS',
|
||||||
data: result,
|
data: result,
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
},
|
},
|
||||||
@ -62,6 +56,5 @@ export const useMetadata = <FinalResult = Metadata>(
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
...queryReturn,
|
...queryReturn,
|
||||||
invalidateMetadata,
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -0,0 +1,41 @@
|
|||||||
|
import { useEffect } from 'react';
|
||||||
|
import { getCurrentReduxResourceVersion } from '../../store/utils';
|
||||||
|
import { useInvalidateMetadata } from './useInvalidateMetadata';
|
||||||
|
import { useMetadata } from './useMetadata';
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* This hook checks if the react-query resource_version is out of sync with the redux store on component mount
|
||||||
|
* If it is, it performs a react-query invalidation of the metadata key and logs the action.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
export const useSyncResourceVersionOnMount = ({
|
||||||
|
componentName,
|
||||||
|
}: {
|
||||||
|
componentName: string;
|
||||||
|
}) => {
|
||||||
|
const { data: reactQueryResourceVersion } = useMetadata(
|
||||||
|
m => m.resource_version
|
||||||
|
);
|
||||||
|
|
||||||
|
const reduxResourceVersion = getCurrentReduxResourceVersion();
|
||||||
|
const invalidateMetadata = useInvalidateMetadata();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (
|
||||||
|
reduxResourceVersion &&
|
||||||
|
reactQueryResourceVersion &&
|
||||||
|
reduxResourceVersion > reactQueryResourceVersion
|
||||||
|
) {
|
||||||
|
invalidateMetadata({
|
||||||
|
componentName,
|
||||||
|
reasons: [
|
||||||
|
`(useSyncResourceVersionOnMount)`,
|
||||||
|
`Resource versions detected to be out of sync on component mount...`,
|
||||||
|
`redux: ${reduxResourceVersion}`,
|
||||||
|
`react-query: ${reactQueryResourceVersion}`,
|
||||||
|
],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
};
|
@ -1,6 +1,6 @@
|
|||||||
import { routerMiddleware } from 'react-router-redux';
|
import { routerMiddleware } from 'react-router-redux';
|
||||||
import { browserHistory } from 'react-router';
|
import { browserHistory } from 'react-router';
|
||||||
import { listenForStoreMetadataChanges } from './store.utils';
|
import { reduxStoreListener } from './store/utils/';
|
||||||
|
|
||||||
// Since we only use it in dev, this warning doesn't make sense.
|
// Since we only use it in dev, this warning doesn't make sense.
|
||||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||||
@ -25,7 +25,7 @@ export const store = configureStore({
|
|||||||
devTools: __DEVELOPMENT__,
|
devTools: __DEVELOPMENT__,
|
||||||
});
|
});
|
||||||
|
|
||||||
listenForStoreMetadataChanges(store);
|
reduxStoreListener(store);
|
||||||
|
|
||||||
// Infer the `RootState` and `AppDispatch` types from the store itself
|
// Infer the `RootState` and `AppDispatch` types from the store itself
|
||||||
export type RootState = ReturnType<typeof store.getState>;
|
export type RootState = ReturnType<typeof store.getState>;
|
||||||
|
@ -1,47 +0,0 @@
|
|||||||
import { ToolkitStore } from '@reduxjs/toolkit/dist/configureStore';
|
|
||||||
import { reactQueryClient } from './lib/reactQuery';
|
|
||||||
import { Metadata } from './features/hasura-metadata-types';
|
|
||||||
import { METADATA_QUERY_KEY } from './features/hasura-metadata-api/useMetadata';
|
|
||||||
|
|
||||||
export const listenForStoreMetadataChanges = (store: ToolkitStore) => {
|
|
||||||
let previousStore: any = null;
|
|
||||||
|
|
||||||
store.subscribe(() => {
|
|
||||||
if (!previousStore || previousStore?.metadata?.metadataObject == null) {
|
|
||||||
previousStore = store.getState();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const currentStore = store.getState();
|
|
||||||
|
|
||||||
const reactQueryResourceVersion =
|
|
||||||
reactQueryClient.getQueryData<Metadata>(
|
|
||||||
METADATA_QUERY_KEY
|
|
||||||
)?.resource_version;
|
|
||||||
|
|
||||||
if (
|
|
||||||
currentStore?.metadata?.resourceVersion >
|
|
||||||
previousStore?.metadata?.resourceVersion &&
|
|
||||||
currentStore?.metadata?.resourceVersion !== reactQueryResourceVersion
|
|
||||||
) {
|
|
||||||
console.groupCollapsed(
|
|
||||||
'Metadata change occurred in redux, and is no longer in sync with react-query:'
|
|
||||||
);
|
|
||||||
|
|
||||||
console.info(
|
|
||||||
`current redux store rv: ${currentStore?.metadata?.resourceVersion}`
|
|
||||||
);
|
|
||||||
console.info(
|
|
||||||
`previous redux store rv: ${previousStore?.metadata?.resourceVersion}`
|
|
||||||
);
|
|
||||||
console.info(`react query rv: ${reactQueryResourceVersion}`);
|
|
||||||
console.info(
|
|
||||||
`Triggering react-query invalidation of query key: ${METADATA_QUERY_KEY}`
|
|
||||||
);
|
|
||||||
console.groupEnd();
|
|
||||||
reactQueryClient.invalidateQueries(METADATA_QUERY_KEY);
|
|
||||||
}
|
|
||||||
|
|
||||||
previousStore = currentStore;
|
|
||||||
});
|
|
||||||
};
|
|
@ -0,0 +1,2 @@
|
|||||||
|
export { reduxStoreListener } from './reduxStoreListener';
|
||||||
|
export { getCurrentReduxResourceVersion } from './store-change-handlers/currentReduxResourceVersion';
|
@ -0,0 +1,10 @@
|
|||||||
|
import { updateReduxResourceVersion } from './store-change-handlers/currentReduxResourceVersion';
|
||||||
|
import { syncResourceVersions } from './store-change-handlers/syncResourceVersions';
|
||||||
|
|
||||||
|
export type OnStoreChangeProps = { currentStore: any; previousStore: any };
|
||||||
|
|
||||||
|
export const onStoreChange = (props: OnStoreChangeProps) => {
|
||||||
|
// execute functions here....
|
||||||
|
syncResourceVersions(props);
|
||||||
|
updateReduxResourceVersion(props);
|
||||||
|
};
|
@ -0,0 +1,21 @@
|
|||||||
|
import { ToolkitStore } from '@reduxjs/toolkit/dist/configureStore';
|
||||||
|
import { onStoreChange } from './onStoreChange';
|
||||||
|
|
||||||
|
// listens for any redux store changes:
|
||||||
|
export const reduxStoreListener = (store: ToolkitStore) => {
|
||||||
|
let previousStore: any = null;
|
||||||
|
|
||||||
|
store.subscribe(() => {
|
||||||
|
if (!previousStore) {
|
||||||
|
previousStore = store.getState();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentStore = store.getState();
|
||||||
|
|
||||||
|
// execute code on store change:
|
||||||
|
onStoreChange({ currentStore, previousStore });
|
||||||
|
|
||||||
|
previousStore = currentStore;
|
||||||
|
});
|
||||||
|
};
|
@ -0,0 +1,19 @@
|
|||||||
|
import type { OnStoreChangeProps } from '../onStoreChange';
|
||||||
|
|
||||||
|
// private module variable
|
||||||
|
let CURRENT_REDUX_RESOURCE_VERSION = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public exported function to read private variable
|
||||||
|
*
|
||||||
|
* This is intended to get the current resourceVersion from redux. Will NOT react to new changes so don't use it as a reactive value
|
||||||
|
*/
|
||||||
|
export const getCurrentReduxResourceVersion = () => {
|
||||||
|
return CURRENT_REDUX_RESOURCE_VERSION;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const updateReduxResourceVersion = ({
|
||||||
|
currentStore,
|
||||||
|
}: OnStoreChangeProps) => {
|
||||||
|
CURRENT_REDUX_RESOURCE_VERSION = currentStore?.metadata?.resourceVersion;
|
||||||
|
};
|
@ -0,0 +1,40 @@
|
|||||||
|
import { MetadataHelpers } from '../../../features/hasura-metadata-api/metadataHelpers';
|
||||||
|
import { logMetadataInvalidation } from '../../../features/hasura-metadata-api/useInvalidateMetadata';
|
||||||
|
import { OnStoreChangeProps } from '../onStoreChange';
|
||||||
|
|
||||||
|
export const syncResourceVersions = ({
|
||||||
|
currentStore,
|
||||||
|
previousStore,
|
||||||
|
}: OnStoreChangeProps) => {
|
||||||
|
if (previousStore.metadata?.metadataObject == null) {
|
||||||
|
// if this is true, then no actual metadata change occurred.
|
||||||
|
// metadata just changed from default state to initial actual metadata
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const redux = {
|
||||||
|
previousResourceVersion: previousStore?.metadata?.resourceVersion,
|
||||||
|
resourceVersion: currentStore?.metadata?.resourceVersion,
|
||||||
|
};
|
||||||
|
const reactQueryResourceVersion =
|
||||||
|
MetadataHelpers.getQueryData()?.resource_version ?? 0;
|
||||||
|
|
||||||
|
if (
|
||||||
|
redux.resourceVersion > redux.previousResourceVersion &&
|
||||||
|
redux.resourceVersion > reactQueryResourceVersion
|
||||||
|
) {
|
||||||
|
// log the invalidation:
|
||||||
|
logMetadataInvalidation({
|
||||||
|
componentName: 'syncResourceVersions() in reduxStoreListener()',
|
||||||
|
reasons: [
|
||||||
|
`Inconsistent resourse version detected between redux and react-query after redux changes:`,
|
||||||
|
`previous redux version: ${redux.previousResourceVersion}`,
|
||||||
|
`current redux version: ${redux.resourceVersion}`,
|
||||||
|
`current react-query version: ${reactQueryResourceVersion}`,
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
// invalidate react-query's metadata key:
|
||||||
|
MetadataHelpers.invalidate();
|
||||||
|
}
|
||||||
|
};
|
@ -2,7 +2,7 @@ import { compose, createStore, applyMiddleware } from 'redux';
|
|||||||
import { routerMiddleware } from 'react-router-redux';
|
import { routerMiddleware } from 'react-router-redux';
|
||||||
import { browserHistory } from 'react-router';
|
import { browserHistory } from 'react-router';
|
||||||
import thunk from 'redux-thunk';
|
import thunk from 'redux-thunk';
|
||||||
import { listenForStoreMetadataChanges } from '@hasura/console-legacy-ce';
|
import { reduxStoreListener } from '@hasura/console-legacy-ce';
|
||||||
|
|
||||||
import reducer from './reducer';
|
import reducer from './reducer';
|
||||||
|
|
||||||
@ -27,6 +27,6 @@ if (__DEVELOPMENT__) {
|
|||||||
|
|
||||||
const store = _finalCreateStore(reducer);
|
const store = _finalCreateStore(reducer);
|
||||||
|
|
||||||
listenForStoreMetadataChanges(store);
|
reduxStoreListener(store);
|
||||||
|
|
||||||
export default store;
|
export default store;
|
||||||
|
Loading…
Reference in New Issue
Block a user