- { /* TODO: call onModified(true) */ }
-
{ compareUrlEditor.current = e }}
- options={{ wordWrap: 'on', wrappingIndent: 'DeepIndent', language: 'typescript', readOnly: !isTester }} />
+
+ { /* TODO: call onModified(true) */}
+ {
+ compareUrlEditor.current = e
+ }}
+ options={{
+ wordWrap: 'on',
+ wrappingIndent: 'DeepIndent',
+ language: 'typescript',
+ readOnly: !isTester
+ }}/>
)
}
+
>);
}
\ No newline at end of file
diff --git a/webapp/src/domain/tests/Hooks.tsx b/webapp/src/domain/tests/Hooks.tsx
new file mode 100644
index 000000000..73d026122
--- /dev/null
+++ b/webapp/src/domain/tests/Hooks.tsx
@@ -0,0 +1,204 @@
+import React, { useEffect, useRef, useState } from 'react';
+import { useDispatch } from 'react-redux'
+import {
+ Button,
+ DataList,
+ DataListAction,
+ DataListItem,
+ DataListItemRow,
+ DataListItemCells,
+ DataListCell,
+ Form,
+ FormGroup,
+ Tab,
+ Tabs,
+ TextInput, FormSelect, FormSelectOption, Title,
+} from '@patternfly/react-core';
+
+import { useTester } from '../../auth'
+
+import { alertAction } from '../../alerts'
+import { TestDispatch } from './reducers';
+import { Hook } from "../hooks/reducers";
+import { TabFunctionsRef } from './Test'
+import {updateHooks} from './actions'
+import { ValueGetter } from '../../components/Editor/monaco/Editor'
+import {eventTypes} from "../hooks/AddHookModal";
+import * as api from "../hooks/api";
+
+function swap(array: any[], i1: number, i2: number) {
+ const temp = array[i1]
+ array[i1] = array[i2]
+ array[i2] = temp
+}
+
+type HookComponentFormProps = {
+ c: Hook,
+ onChange(): void,
+ isTester: boolean,
+}
+
+
+
+const HookComponentForm = ({ c, onChange, isTester } : HookComponentFormProps) => {
+ const [eventType,setEventType] = useState(c.type)
+
+ return (
+
+ )
+
+}
+
+type HooksProps = {
+ testId: number,
+ // testWebHooks: TestWebHooks,
+ testOwner?: string,
+ funcsRef: TabFunctionsRef,
+ onModified(modified: boolean): void,
+}
+
+export default ({ testId, testOwner, funcsRef, onModified }: HooksProps) => {
+ const [testWebHooks, setTestWebHooks] = useState([])
+ const isTester = useTester(testOwner)
+ const renderRefs = useRef(new Array(testWebHooks.length));
+
+ useEffect(() => {
+ if (!testId) {
+ return
+ }
+ api.fetchHooks(testId).then(
+ response => {
+ setTestWebHooks(response.map((h: Hook) => {
+ let hd: Hook = {
+ ...h,
+ id: Number(h.id),
+ url: String(h.url),
+ active: Boolean(h.active),
+ target: Number(h.target),
+ type: String(h.type),
+ }
+ return hd
+ }))
+
+ // setGroups(groupNames(response))
+ // calculations.current.splice(0)
+ // response.forEach((_: any) => calculations.current.push(undefined));
+ },
+ error => dispatch(alertAction("HOOK_FETCH", "Failed to fetch webhooks", error))
+ )
+ }, [testId])
+
+
+ const dispatch = useDispatch()
+ const thunkDispatch = useDispatch()
+ funcsRef.current = {
+ save: () => thunkDispatch(updateHooks(testId, testWebHooks)).catch(
+ error => {
+ dispatch(alertAction("HOOK_UPDATE", "Hook update failed", error))
+ return Promise.reject()
+ }
+ ),
+ reset: () => {
+ // Perform a deep copy of the view object to prevent modifying store
+ setTestWebHooks(JSON.parse(JSON.stringify(testWebHooks)) as Hook[])
+ }
+ }
+
+ return (<>
+
+
Webhooks
+
+
+
+
+ { (!testWebHooks || testWebHooks.length === 0) && "The are no Webhooks defined" }
+
+
+ >)
+}
\ No newline at end of file
diff --git a/webapp/src/domain/tests/Test.tsx b/webapp/src/domain/tests/Test.tsx
index a85c5ff07..db662d6b8 100644
--- a/webapp/src/domain/tests/Test.tsx
+++ b/webapp/src/domain/tests/Test.tsx
@@ -9,7 +9,7 @@ import {
Button,
Card,
CardBody,
- CardFooter,
+ CardFooter, Grid,
Spinner,
Tab,
Tabs,
@@ -25,12 +25,16 @@ import { infoActions } from '../../alerts'
import General from './General'
import Views from './Views'
import Variables from './Variables'
+import Hooks from "./Hooks";
+// import Hooks from "./Hooks";
function initialActiveTab(location: Location) {
if (location.hash.startsWith("#views")) {
return 1;
} else if (location.hash.startsWith("#vars")) {
return 2;
+ } else if (location.hash.startsWith("#hooks")) {
+ return 3;
} else {
return 0;
}
@@ -57,8 +61,9 @@ export default () => {
const generalFuncsRef = useRef()
const viewFuncsRef = useRef()
const variablesFuncsRef = useRef()
- const funcRefs = [ generalFuncsRef, viewFuncsRef, variablesFuncsRef ]
- const tabs = [ "general", "views", "vars"]
+ const hooksFuncsRef = useRef()
+ const funcRefs = [ generalFuncsRef, viewFuncsRef, variablesFuncsRef, hooksFuncsRef ]
+ const tabs = [ "general", "views", "vars", "hooks"]
const gotoTab = (index: number) => {
setActiveTab(index)
setNextTab(index)
@@ -148,7 +153,15 @@ export default () => {
testName={ test && test.name || ""}
testOwner={ test ? test.owner : undefined }
onModified={ setModified }
- funcsRef={variablesFuncsRef}
+ funcsRef={ variablesFuncsRef }
+ />
+
+
+
diff --git a/webapp/src/domain/tests/actionTypes.ts b/webapp/src/domain/tests/actionTypes.ts
index 3e2a5da04..f9ee621dc 100644
--- a/webapp/src/domain/tests/actionTypes.ts
+++ b/webapp/src/domain/tests/actionTypes.ts
@@ -8,3 +8,4 @@ export const UPDATE_TOKEN = "tests/UPDATE_TOKEN"
export const UPDATE_ACCESS= "tests/UPDATE_ACCESS"
export const UPDATE_TEST_WATCH = "tests/UPDATE_TEST_WATCH"
export const UPDATE_VIEW = "Tests/UPDATE_VIEW"
+export const UPDATE_HOOK = "Tests/UPDATE_HOOK"
diff --git a/webapp/src/domain/tests/actions.ts b/webapp/src/domain/tests/actions.ts
index d60c766f8..8ec4a3722 100644
--- a/webapp/src/domain/tests/actions.ts
+++ b/webapp/src/domain/tests/actions.ts
@@ -1,11 +1,23 @@
import * as api from './api';
import * as actionTypes from './actionTypes';
import { accessName, Access } from '../../auth'
-import { Test, View, LoadingAction, LoadedAction, UpdateTokenAction, UpdateAccessAction, DeleteAction, UpdateTestWatchAction, UpdateViewAction } from './reducers';
+import {
+ Test,
+ View,
+ LoadingAction,
+ LoadedAction,
+ UpdateTokenAction,
+ UpdateAccessAction,
+ DeleteAction,
+ UpdateTestWatchAction,
+ UpdateViewAction,
+ UpdateHookAction,
+} from './reducers';
import { Dispatch } from 'react';
import * as notifications from '../../usersettings'
import { Map } from 'immutable';
import { alertAction, AddAlertAction } from '../../alerts'
+import {Hook} from "../hooks/reducers";
const loaded = (tests: Test | Test[]): LoadedAction =>({
type: actionTypes.LOADED,
@@ -46,6 +58,25 @@ export const updateView = (testId: number, view: View) => (dispatch: Dispatch (dispatch: Dispatch) => {
+
+ const promises: any[] = [] ;
+
+ testWebHooks.forEach( hook => {
+ promises.push( api.updateHook(testId, hook).then(
+ response => {
+ dispatch({
+ type: actionTypes.UPDATE_HOOK,
+ testId, hook
+ })
+ return response
+ }
+ )
+ )
+ })
+ return Promise.all(promises);
+}
+
export const resetToken = (id: number) => (dispatch: Dispatch) =>
api.resetToken(id).then(
token => dispatch({
diff --git a/webapp/src/domain/tests/api.ts b/webapp/src/domain/tests/api.ts
index 005f0613a..1550a5f60 100644
--- a/webapp/src/domain/tests/api.ts
+++ b/webapp/src/domain/tests/api.ts
@@ -1,5 +1,6 @@
import { fetchApi } from '../../services/api';
import { Test, View } from './reducers';
+import {Hook} from "../hooks/reducers";
const base = "/api/test"
const endPoints = {
@@ -7,6 +8,7 @@ const endPoints = {
crud: (id: number)=>`${base}/${id}`,
schema: (id: number)=>`${base}/${id}/schema`,
view: (id: number)=>`${base}/${id}/view`,
+ hook: (id: number)=>`${base}/${id}/hook`,
summary: ()=>`${base}/summary`,
resetToken: (id: number) => `${base}/${id}/resetToken`,
dropToken: (id: number) => `${base}/${id}/dropToken`,
@@ -16,6 +18,9 @@ const endPoints = {
export const updateView = (testId: number, view: View) => {
return fetchApi(endPoints.view(testId), view, 'post')
}
+export const updateHook = (testId: number, hook: Hook) => {
+ return fetchApi(endPoints.hook(testId), hook, 'post')
+}
export const get = (id: number) => {
return fetchApi(endPoints.crud(id),null,'get')
}
diff --git a/webapp/src/domain/tests/reducers.ts b/webapp/src/domain/tests/reducers.ts
index d5243bcfa..1c4e5f3a4 100644
--- a/webapp/src/domain/tests/reducers.ts
+++ b/webapp/src/domain/tests/reducers.ts
@@ -3,6 +3,7 @@ import {Map} from 'immutable';
import * as utils from "../../utils";
import { Access } from "../../auth"
import { ThunkDispatch } from 'redux-thunk';
+import {Hook} from "../hooks/reducers";
export interface ViewComponent {
headerName: string,
@@ -76,7 +77,13 @@ export interface UpdateViewAction {
view: View,
}
-export type TestAction = LoadingAction | LoadedAction | DeleteAction | UpdateTokenAction | UpdateAccessAction | UpdateTestWatchAction | UpdateViewAction
+export interface UpdateHookAction {
+ type: typeof actionTypes.UPDATE_HOOK,
+ testId: number,
+ hook: Hook,
+}
+
+export type TestAction = LoadingAction | LoadedAction | DeleteAction | UpdateTokenAction | UpdateAccessAction | UpdateTestWatchAction | UpdateViewAction | UpdateHookAction
export type TestDispatch = ThunkDispatch
@@ -129,6 +136,10 @@ export const reducer = (state = new TestsState(), action: TestAction) => {
state.byId = state.byId?.set(action.testId, { ...test, defaultView: action.view })
}
}
+ break;
+ case actionTypes.UPDATE_HOOK: {
+ //TODO: define state changes
+ }
default:
}
return state;
diff --git a/webapp/src/index.css b/webapp/src/index.css
index c6ea142d9..8dd25f2eb 100644
--- a/webapp/src/index.css
+++ b/webapp/src/index.css
@@ -30,3 +30,7 @@ code {
/* This makes selects correctly display in modals */
overflow: visible !important
}
+
+.pf-c-tab-content {
+ margin: 20px !important;
+}
diff --git a/webapp/src/store.ts b/webapp/src/store.ts
index f4ea59b50..9c8551338 100644
--- a/webapp/src/store.ts
+++ b/webapp/src/store.ts
@@ -10,6 +10,7 @@ import { HooksState, reducer as hookReducer} from './domain/hooks/reducers'
import { SchemasState, reducer as schemaReducer} from './domain/schemas/reducers'
import { AuthState, reducer as authReducer} from './auth'
import { Alert, reducer as alertReducer } from './alerts'
+import {enableDevMode} from "./utils";
export const history = createBrowserHistory();
@@ -35,6 +36,7 @@ const enhancer = compose(
applyMiddleware(
thunk,
),
+ enableDevMode(),
)
const store = createStore(
appReducers,
diff --git a/webapp/src/utils.ts b/webapp/src/utils.ts
index 5f3f80754..adcbd810a 100644
--- a/webapp/src/utils.ts
+++ b/webapp/src/utils.ts
@@ -46,4 +46,12 @@ export type PaginationInfo = {
perPage: number,
sort: string,
direction: string,
+}
+
+export function enableDevMode() {
+ if (!process.env.NODE_ENV || process.env.NODE_ENV === 'development') {
+ return (window as any).__REDUX_DEVTOOLS_EXTENSION__ && (window as any).__REDUX_DEVTOOLS_EXTENSION__();
+ } else {
+ return;
+ }
}
\ No newline at end of file