mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-15 09:22:43 +03:00
console: handle renaming cron triggers (#5167)
This commit is contained in:
parent
ea23571049
commit
9936ace6ab
@ -1,4 +1,4 @@
|
||||
import React from 'react';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import Helmet from 'react-helmet';
|
||||
import CommonTabLayout from '../../../Common/Layout/CommonTabLayout/CommonTabLayout';
|
||||
import {
|
||||
@ -21,7 +21,12 @@ interface Props {
|
||||
allTriggers: Triggers;
|
||||
tabName: STTab;
|
||||
dispatch: Dispatch;
|
||||
eventsLoading?: boolean;
|
||||
}
|
||||
type TriggerPresence =
|
||||
| 'not-missing'
|
||||
| { type: 'timeout'; timeoutHandle: number }
|
||||
| 'error-not-found';
|
||||
|
||||
const STContainer: React.FC<Props> = ({
|
||||
triggerName,
|
||||
@ -29,7 +34,11 @@ const STContainer: React.FC<Props> = ({
|
||||
allTriggers,
|
||||
tabName,
|
||||
dispatch,
|
||||
eventsLoading,
|
||||
}) => {
|
||||
const [triggerPresence, setTriggerPresence] = useState<TriggerPresence>(
|
||||
'not-missing'
|
||||
);
|
||||
React.useEffect(() => {
|
||||
dispatch(setCurrentTrigger(triggerName));
|
||||
return () => {
|
||||
@ -39,8 +48,28 @@ const STContainer: React.FC<Props> = ({
|
||||
|
||||
const currentTrigger = findScheduledTrigger(allTriggers, triggerName);
|
||||
|
||||
// TODO: This is a hack to deal with renaming cron triggers and stale props
|
||||
// https://react-redux.js.org/api/hooks#stale-props-and-zombie-children
|
||||
// Needs remodelling the state and careful handling of cron triggers rename
|
||||
useEffect(() => {
|
||||
if (currentTrigger) {
|
||||
if (
|
||||
typeof triggerPresence === 'object' &&
|
||||
triggerPresence.type === 'timeout'
|
||||
) {
|
||||
window.clearTimeout(triggerPresence.timeoutHandle);
|
||||
setTriggerPresence('not-missing');
|
||||
}
|
||||
} else if (triggerPresence === 'not-missing') {
|
||||
const timeoutHandle = window.setTimeout(() => {
|
||||
setTriggerPresence('error-not-found');
|
||||
}, 1200 /* arbitrary value */);
|
||||
setTriggerPresence({ type: 'timeout', timeoutHandle });
|
||||
}
|
||||
}, [currentTrigger]);
|
||||
|
||||
if (!currentTrigger) {
|
||||
dispatch(setCurrentTrigger(''));
|
||||
if (eventsLoading || triggerPresence !== 'error-not-found') return null;
|
||||
throw new NotFoundError();
|
||||
}
|
||||
|
||||
|
@ -1,21 +1,27 @@
|
||||
import React from 'react';
|
||||
import { connect, ConnectedProps } from 'react-redux';
|
||||
import STContainer from '../Container';
|
||||
import { Triggers, RouterTriggerProps } from '../../types';
|
||||
import { MapStateToProps } from '../../../../../types';
|
||||
import Modify from './Modify';
|
||||
import { mapDispatchToPropsEmpty } from '../../../../Common/utils/reactUtils';
|
||||
import { ReduxState } from '../../../../../types';
|
||||
|
||||
interface Props extends InjectedProps {}
|
||||
|
||||
const ModifyContainer: React.FC<Props> = props => {
|
||||
const { dispatch, allTriggers, triggerName, readOnlyMode } = props;
|
||||
const {
|
||||
dispatch,
|
||||
allTriggers,
|
||||
triggerName,
|
||||
readOnlyMode,
|
||||
eventsLoading,
|
||||
} = props;
|
||||
return (
|
||||
<STContainer
|
||||
tabName="modify"
|
||||
dispatch={dispatch}
|
||||
triggerName={triggerName}
|
||||
allTriggers={allTriggers}
|
||||
eventsLoading={eventsLoading}
|
||||
>
|
||||
{readOnlyMode ? (
|
||||
'Cannot modify in read-only mode'
|
||||
@ -26,20 +32,15 @@ const ModifyContainer: React.FC<Props> = props => {
|
||||
);
|
||||
};
|
||||
|
||||
type PropsFromState = {
|
||||
allTriggers: Triggers;
|
||||
triggerName: string;
|
||||
readOnlyMode: boolean;
|
||||
};
|
||||
|
||||
const mapStateToProps: MapStateToProps<PropsFromState, RouterTriggerProps> = (
|
||||
state,
|
||||
ownProps
|
||||
const mapStateToProps = (
|
||||
state: ReduxState,
|
||||
ownProps: { params: { triggerName: string } }
|
||||
) => {
|
||||
return {
|
||||
allTriggers: state.events.triggers,
|
||||
readOnlyMode: state.main.readOnlyMode,
|
||||
triggerName: ownProps.params.triggerName,
|
||||
eventsLoading: state.events.loading,
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { push } from 'react-router-redux';
|
||||
import { push, replace } from 'react-router-redux';
|
||||
import {
|
||||
fetchEventTriggersQuery,
|
||||
fetchScheduledTriggersQuery,
|
||||
@ -35,8 +35,14 @@ import {
|
||||
EventTrigger,
|
||||
EventKind,
|
||||
InvocationLog,
|
||||
LOADING_TRIGGERS,
|
||||
} from './types';
|
||||
import { setScheduledTriggers, setEventTriggers, setTriggers } from './reducer';
|
||||
import {
|
||||
setScheduledTriggers,
|
||||
setEventTriggers,
|
||||
setTriggers,
|
||||
setCurrentTrigger,
|
||||
} from './reducer';
|
||||
import { LocalScheduledTriggerState } from './CronTriggers/state';
|
||||
import { LocalAdhocEventState } from './AdhocEvents/Add/state';
|
||||
import {
|
||||
@ -59,6 +65,8 @@ import { getLogsTableDef } from './utils';
|
||||
export const fetchTriggers = (
|
||||
kind: Nullable<TriggerKind>
|
||||
): Thunk<Promise<void>> => (dispatch, getState) => {
|
||||
dispatch({ type: LOADING_TRIGGERS });
|
||||
|
||||
const bulkQueryArgs = [];
|
||||
if (kind) {
|
||||
bulkQueryArgs.push(
|
||||
@ -194,8 +202,8 @@ export const saveScheduledTrigger = (
|
||||
);
|
||||
|
||||
const upRenameQueries = [
|
||||
getDropScheduledTriggerQuery(existingTrigger.name),
|
||||
generateCreateScheduledTriggerQuery(state),
|
||||
getDropScheduledTriggerQuery(existingTrigger.name),
|
||||
];
|
||||
const downRenameQueries = [
|
||||
getDropScheduledTriggerQuery(state.name),
|
||||
@ -209,17 +217,18 @@ export const saveScheduledTrigger = (
|
||||
const successMsg = 'Updated scheduled trigger successfully';
|
||||
|
||||
const customOnSuccess = () => {
|
||||
return dispatch(fetchTriggers('cron'))
|
||||
.then(() => {
|
||||
if (successCb) {
|
||||
successCb();
|
||||
}
|
||||
if (isRenamed) {
|
||||
const newHref = window.location.href.replace(
|
||||
getSTModifyRoute(existingTrigger.name, 'relative'),
|
||||
getSTModifyRoute(state.name, 'relative')
|
||||
);
|
||||
return window.location.replace(newHref);
|
||||
}
|
||||
return dispatch(fetchTriggers('cron'))
|
||||
.then(() => {
|
||||
if (successCb) {
|
||||
successCb();
|
||||
dispatch(replace(newHref));
|
||||
dispatch(setCurrentTrigger(state.name));
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
|
@ -12,6 +12,7 @@ import {
|
||||
RASetCurrentTrigger,
|
||||
RASetEventTriggers,
|
||||
RASetScheduledTriggers,
|
||||
LOADING_TRIGGERS,
|
||||
} from './types';
|
||||
|
||||
export const setTriggers = (data: Triggers): RASetAllTriggers => ({
|
||||
@ -41,6 +42,7 @@ const reducer = (state = defaultState, action: RAEvents) => {
|
||||
return {
|
||||
...state,
|
||||
triggers: action.data,
|
||||
loading: false,
|
||||
};
|
||||
case LOADED_SCHEDULED_TRIGGERS:
|
||||
return {
|
||||
@ -49,6 +51,7 @@ const reducer = (state = defaultState, action: RAEvents) => {
|
||||
...state.triggers,
|
||||
scheduled: action.data,
|
||||
},
|
||||
loading: false,
|
||||
};
|
||||
case LOADED_EVENT_TRIGGERS:
|
||||
return {
|
||||
@ -57,12 +60,18 @@ const reducer = (state = defaultState, action: RAEvents) => {
|
||||
...state.triggers,
|
||||
event: action.data,
|
||||
},
|
||||
loading: false,
|
||||
};
|
||||
case SET_CURRENT_TRIGGER:
|
||||
return {
|
||||
...state,
|
||||
currentTrigger: action.name,
|
||||
};
|
||||
case LOADING_TRIGGERS:
|
||||
return {
|
||||
...state,
|
||||
loading: true,
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
@ -3,9 +3,7 @@ import { Triggers } from './types';
|
||||
export type EventsState = {
|
||||
triggers: Triggers;
|
||||
currentTrigger: string;
|
||||
loading: {
|
||||
[component: string]: boolean;
|
||||
};
|
||||
loading: boolean;
|
||||
error: {
|
||||
[component: string]: any;
|
||||
};
|
||||
@ -17,7 +15,7 @@ const state: EventsState = {
|
||||
event: [],
|
||||
},
|
||||
currentTrigger: '',
|
||||
loading: {},
|
||||
loading: true,
|
||||
error: {},
|
||||
};
|
||||
|
||||
|
@ -6,11 +6,8 @@ import { Dispatch } from '../../../types';
|
||||
|
||||
export const LOADING_TRIGGERS = 'Events/LOADING_TRIGGERS';
|
||||
export const LOADED_TRIGGERS = 'Events/LOADED_TRIGGERS';
|
||||
export const LOADING_SCHEDULED_TRIGGERS = 'Events/LOADING_SCHEDULED_TRIGGERS';
|
||||
export const LOADED_SCHEDULED_TRIGGERS = 'Events/LOADED_SCHEDULED_TRIGGERS';
|
||||
export const LOADING_EVENT_TRIGGERS = 'Events/LOADING_EVENT_TRIGGERS';
|
||||
export const LOADED_EVENT_TRIGGERS = 'Events/LOADED_EVENT_TRIGGERS';
|
||||
export const LOADING_TRIGGERS_ERROR = 'Events/LOADING_TRIGGERS_ERROR';
|
||||
export const SET_CURRENT_TRIGGER = 'Events/SET_CURRENT_TRIGGER';
|
||||
export const LOAD_PENDING_DATA_EVENTS = 'Events/LOAD_PENDING_DATA_EVENTS';
|
||||
|
||||
@ -161,4 +158,5 @@ export type RAEvents =
|
||||
| RASetAllTriggers
|
||||
| RASetScheduledTriggers
|
||||
| RASetEventTriggers
|
||||
| RASetCurrentTrigger;
|
||||
| RASetCurrentTrigger
|
||||
| { type: typeof LOADING_TRIGGERS };
|
||||
|
Loading…
Reference in New Issue
Block a user