diff --git a/frontend/common/providers/withWebhooks.js b/frontend/common/providers/withWebhooks.js
deleted file mode 100644
index 7ec473328fab..000000000000
--- a/frontend/common/providers/withWebhooks.js
+++ /dev/null
@@ -1,70 +0,0 @@
-import data from 'common/data/base/_data'
-
-export default (WrappedComponent) => {
- class HOC extends React.Component {
- static displayName = 'withWebhooks'
-
- getWebhooks = () =>
- data
- .get(
- `${Project.api}environments/${this.props.match.params.environmentId}/webhooks/`,
- )
- .then((webhooks) => {
- this.setState({
- webhooks,
- webhooksLoading: false,
- })
- })
-
- deleteWebhook = (webhook) => {
- this.setState({ webhooksLoading: true })
- return data
- .delete(
- `${Project.api}environments/${this.props.match.params.environmentId}/webhooks/${webhook.id}/`,
- )
- .then(() => {
- this.getWebhooks()
- })
- }
-
- saveWebhook = (webhook) => {
- this.setState({ webhooksLoading: true })
- return data
- .put(
- `${Project.api}environments/${this.props.match.params.environmentId}/webhooks/${webhook.id}/`,
- webhook,
- )
- .then(() => {
- this.getWebhooks()
- })
- }
-
- createWebhook = (webhook) => {
- this.setState({ webhooksLoading: true })
- return data
- .post(
- `${Project.api}environments/${this.props.match.params.environmentId}/webhooks/`,
- webhook,
- )
- .then(() => {
- this.getWebhooks()
- })
- }
-
- render() {
- return (
-
- )
- }
- }
-
- return HOC
-}
diff --git a/frontend/common/services/useWebhooks.ts b/frontend/common/services/useWebhooks.ts
new file mode 100644
index 000000000000..4ef5cd69572a
--- /dev/null
+++ b/frontend/common/services/useWebhooks.ts
@@ -0,0 +1,102 @@
+import { service } from 'common/service'
+import { Res } from 'common/types/responses'
+import { Req } from 'common/types/requests'
+
+export const webhookService = service
+ .enhanceEndpoints({ addTagTypes: ['Webhooks'] })
+ .injectEndpoints({
+ endpoints: (builder) => ({
+ createWebhook: builder.mutation({
+ invalidatesTags: [{ id: 'LIST', type: 'Webhooks' }],
+ query: ({ environmentId, ...rest }) => ({
+ body: {
+ ...rest,
+ },
+ method: 'POST',
+ url: `environments/${environmentId}/webhooks/`,
+ }),
+ }),
+
+ deleteWebhook: builder.mutation({
+ invalidatesTags: [{ id: 'LIST', type: 'Webhooks' }],
+ query: (query) => ({
+ method: 'DELETE',
+ url: `environments/${query.environmentId}/webhooks/${query.id}/`,
+ }),
+ }),
+
+ getWebhooks: builder.query({
+ providesTags: [{ id: 'LIST', type: 'Webhooks' }],
+ query: (query) => ({
+ url: `environments/${query.environmentId}/webhooks/`,
+ }),
+ }),
+
+ updateWebhook: builder.mutation({
+ invalidatesTags: [{ id: 'LIST', type: 'Webhooks' }],
+ query: ({ environmentId, ...rest }) => ({
+ body: {
+ ...rest,
+ },
+ method: 'PUT',
+ url: `environments/${environmentId}/webhooks/${rest.id}/`,
+ }),
+ }),
+ }),
+ })
+
+export async function createWebhook(
+ store: any,
+ data: Req['createWebhook'],
+ options?: Parameters<
+ typeof webhookService.endpoints.createWebhook.initiate
+ >[1],
+) {
+ return store.dispatch(
+ webhookService.endpoints.createWebhook.initiate(data, options),
+ )
+}
+export async function getWebhooks(
+ store: any,
+ data: Req['getWebhooks'],
+ options?: Parameters[1],
+) {
+ return store.dispatch(
+ webhookService.endpoints.getWebhooks.initiate(data, options),
+ )
+}
+export async function updateWebhook(
+ store: any,
+ data: Req['updateWebhook'],
+ options?: Parameters<
+ typeof webhookService.endpoints.updateWebhook.initiate
+ >[1],
+) {
+ return store.dispatch(
+ webhookService.endpoints.deleteWebhook.initiate(data, options),
+ )
+}
+export async function deleteWebhook(
+ store: any,
+ data: Req['deleteWebhook'],
+ options?: Parameters<
+ typeof webhookService.endpoints.deleteWebhook.initiate
+ >[1],
+) {
+ return store.dispatch(
+ webhookService.endpoints.deleteWebhook.initiate(data, options),
+ )
+}
+
+export const {
+ useCreateWebhookMutation,
+ useDeleteWebhookMutation,
+ useGetWebhooksQuery,
+ useUpdateWebhookMutation,
+} = webhookService
+
+/* Usage examples:
+const { data, isLoading } = useGetWebhooksQuery({ environmentId: 1 }) //get hook
+const [createWebhook, { isLoading, data, isSuccess }] = useCreateWebhookMutation() //create hook
+webhookService.endpoints.getWebhooks.select({id: 2})(store.getState()) //access data from any function
+*/
diff --git a/frontend/common/types/requests.ts b/frontend/common/types/requests.ts
index ab22c7ac00ee..2207a01f3d2c 100644
--- a/frontend/common/types/requests.ts
+++ b/frontend/common/types/requests.ts
@@ -91,6 +91,26 @@ export type Req = {
| 'previous_billing_period'
| '90_day_period'
}
+ getWebhooks: {
+ environmentId: string
+ }
+ createWebhook: {
+ environmentId: string
+ enabled: boolean
+ secret: string
+ url: string
+ }
+ updateWebhook: {
+ id: number
+ environmentId: string
+ enabled: boolean
+ secret: string
+ url: string
+ }
+ deleteWebhook: {
+ id: number
+ environmentId: string
+ }
deleteIdentity: {
id: string
environmentId: string
diff --git a/frontend/common/types/responses.ts b/frontend/common/types/responses.ts
index ea8c3d03c246..a48f6a98ecb4 100644
--- a/frontend/common/types/responses.ts
+++ b/frontend/common/types/responses.ts
@@ -658,6 +658,15 @@ export type HealthProvider = {
webhook_url: number
}
+export type Webhook = {
+ id: number
+ url: string
+ secret: string
+ enabled: boolean
+ created_at: string
+ updated_at: string
+}
+
export type Res = {
segments: PagedResponse
segment: Segment
@@ -667,6 +676,8 @@ export type Res = {
projects: ProjectSummary[]
project: Project
environments: PagedResponse
+ webhook: Webhook
+ webhooks: Webhook[]
organisationUsage: {
totals: {
flags: number
diff --git a/frontend/web/components/pages/EnvironmentSettingsPage.js b/frontend/web/components/pages/EnvironmentSettingsPage.js
index b7f2e2431c0c..d931a5c4f454 100644
--- a/frontend/web/components/pages/EnvironmentSettingsPage.js
+++ b/frontend/web/components/pages/EnvironmentSettingsPage.js
@@ -2,7 +2,6 @@ import React, { Component } from 'react'
import ConfirmRemoveEnvironment from 'components/modals/ConfirmRemoveEnvironment'
import ProjectStore from 'common/stores/project-store'
import ConfigProvider from 'common/providers/ConfigProvider'
-import withWebhooks from 'common/providers/withWebhooks'
import CreateWebhookModal from 'components/modals/CreateWebhook'
import ConfirmRemoveWebhook from 'components/modals/ConfirmRemoveWebhook'
import ConfirmToggleEnvFeature from 'components/modals/ConfirmToggleEnvFeature'
@@ -26,6 +25,12 @@ import { getSupportedContentType } from 'common/services/useSupportedContentType
import EnvironmentVersioningListener from 'components/EnvironmentVersioningListener'
import Format from 'common/utils/format'
import Setting from 'components/Setting'
+import {
+ createWebhook,
+ deleteWebhook,
+ getWebhooks,
+ updateWebhook,
+} from 'common/services/useWebhooks'
const showDisabledFlagOptions = [
{ label: 'Inherit from Project', value: null },
@@ -47,6 +52,8 @@ const EnvironmentSettingsPage = class extends Component {
environmentContentType: {},
roles: [],
showMetadataList: false,
+ webhooks: [],
+ webhooksLoading: true,
}
AppActions.getProject(this.props.match.params.projectId)
}
@@ -54,7 +61,22 @@ const EnvironmentSettingsPage = class extends Component {
componentDidMount = () => {
API.trackPage(Constants.pages.ENVIRONMENT_SETTINGS)
this.getEnvironment()
- this.props.getWebhooks()
+ this.fetchWebhooks(this.props.match.params.environmentId)
+ }
+
+ fetchWebhooks = (environmentId) => {
+ if (!environmentId) return
+
+ this.setState({ webhooksLoading: true })
+ getWebhooks(getStore(), { environmentId })
+ .then((res) => {
+ this.setState({
+ webhooks: res.data,
+ })
+ })
+ .finally(() => {
+ this.setState({ webhooksLoading: false })
+ })
}
getEnvironment = () => {
@@ -97,7 +119,7 @@ const EnvironmentSettingsPage = class extends Component {
this.setState({ environmentContentType: environmentContentType })
})
}
- this.props.getWebhooks()
+ this.fetchWebhooks(this.props.match.params.environmentId)
}
onSave = () => {
@@ -200,7 +222,16 @@ const EnvironmentSettingsPage = class extends Component {
router={this.context.router}
environmentId={this.props.match.params.environmentId}
projectId={this.props.match.params.projectId}
- save={this.props.createWebhook}
+ save={(webhook) =>
+ createWebhook(getStore(), {
+ environmentId: this.props.match.params.environmentId,
+ ...webhook,
+ }).then((res) => {
+ this.setState({
+ webhooks: this.state.webhooks.concat(res.data),
+ })
+ })
+ }
/>,
'side-modal',
)
@@ -215,7 +246,18 @@ const EnvironmentSettingsPage = class extends Component {
isEdit
environmentId={this.props.match.params.environmentId}
projectId={this.props.match.params.projectId}
- save={this.props.saveWebhook}
+ save={(webhook) =>
+ updateWebhook(getStore(), {
+ environmentId: this.props.match.params.environmentId,
+ ...webhook,
+ }).then(() => {
+ this.setState({
+ webhooks: this.state.webhooks.map((w) =>
+ w.id === webhook.id ? webhook : w,
+ ),
+ })
+ })
+ }
/>,
'side-modal',
)
@@ -228,7 +270,16 @@ const EnvironmentSettingsPage = class extends Component {
environmentId={this.props.match.params.environmentId}
projectId={this.props.match.params.projectId}
url={webhook.url}
- cb={() => this.props.deleteWebhook(webhook)}
+ cb={() =>
+ deleteWebhook(getStore(), {
+ environmentId: this.props.match.params.environmentId,
+ id: webhook.id,
+ }).then(() => {
+ this.setState({
+ webhooks: this.state.webhooks.filter((w) => w.id !== webhook.id),
+ })
+ })
+ }
/>,
'p-0',
)
@@ -255,7 +306,6 @@ const EnvironmentSettingsPage = class extends Component {
render() {
const {
- props: { webhooks, webhooksLoading },
state: {
allow_client_traits,
hide_sensitive_data,
@@ -263,6 +313,8 @@ const EnvironmentSettingsPage = class extends Component {
use_identity_composite_key_for_hashing,
use_identity_overrides_in_local_eval,
use_v2_feature_versioning,
+ webhooks,
+ webhooksLoading,
},
} = this
const has4EyesPermission = Utils.getPlansPermission('4_EYES')
@@ -917,4 +969,4 @@ const EnvironmentSettingsPage = class extends Component {
EnvironmentSettingsPage.propTypes = {}
-module.exports = ConfigProvider(withWebhooks(EnvironmentSettingsPage))
+module.exports = ConfigProvider(EnvironmentSettingsPage)