mirror of
https://github.com/harness/drone.git
synced 2025-05-07 07:39:03 +08:00
feat: [AH-883]: Implement edit webhook page (#3291)
* feat: [AH-883]: refetch webhook after update and fix route to webhook details page from webhook list page * feat: [AH-883]: fix breaking css for inline inputs * feat: [AH-883]: implement Edit flow with enterprise secret input * feat: [AH-883]: Implement edit webhook page
This commit is contained in:
parent
b6c214b9ee
commit
b00a8f16b4
@ -28,6 +28,7 @@ import upstreamProxyDetails from '@ar/pages/upstream-proxy-details/strings/strin
|
|||||||
import versionDetails from '@ar/pages/version-details/strings/strings.en.yaml'
|
import versionDetails from '@ar/pages/version-details/strings/strings.en.yaml'
|
||||||
import versionList from '@ar/pages/version-list/strings/strings.en.yaml'
|
import versionList from '@ar/pages/version-list/strings/strings.en.yaml'
|
||||||
import webhookList from '@ar/pages/webhook-list/strings/strings.en.yaml'
|
import webhookList from '@ar/pages/webhook-list/strings/strings.en.yaml'
|
||||||
|
import webhookDetails from '@ar/pages/webhook-details/strings/strings.en.yaml'
|
||||||
|
|
||||||
export default function languageLoader() {
|
export default function languageLoader() {
|
||||||
return {
|
return {
|
||||||
@ -39,6 +40,7 @@ export default function languageLoader() {
|
|||||||
upstreamProxyDetails,
|
upstreamProxyDetails,
|
||||||
versionDetails,
|
versionDetails,
|
||||||
versionList,
|
versionList,
|
||||||
webhookList
|
webhookList,
|
||||||
|
webhookDetails
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,8 @@ export default function getARRouteDefinitions(routeParams: Record<string, string
|
|||||||
`/${params?.repositoryIdentifier}/artifacts/${params?.artifactIdentifier}/versions/${params?.versionIdentifier}`,
|
`/${params?.repositoryIdentifier}/artifacts/${params?.artifactIdentifier}/versions/${params?.versionIdentifier}`,
|
||||||
// anything random, as this route will not be used in gitness
|
// anything random, as this route will not be used in gitness
|
||||||
toARVersionDetailsTab: params =>
|
toARVersionDetailsTab: params =>
|
||||||
`/${params?.repositoryIdentifier}/artifacts/${params?.artifactIdentifier}/versions/${params?.versionIdentifier}`
|
`/${params?.repositoryIdentifier}/artifacts/${params?.artifactIdentifier}/versions/${params?.versionIdentifier}`,
|
||||||
|
toARRepositoryWebhookDetailsTab: params =>
|
||||||
|
`/${params?.repositoryIdentifier}/webhooks/${params?.webhookIdentifier}/${params?.tab}`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -123,7 +123,7 @@ export function getFormattedFormDataForAuthType(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSecretScopeDetailsByIdentifier(identifier: string, secretSpacePath: string) {
|
export function getSecretScopeDetailsByIdentifier(identifier: string, secretSpacePath: string) {
|
||||||
const referenceString = getReferenceStringFromSecretSpacePath(identifier, secretSpacePath)
|
const referenceString = getReferenceStringFromSecretSpacePath(identifier, secretSpacePath)
|
||||||
const [, orgIdentifier, projectIdentifier] = secretSpacePath.split('/')
|
const [, orgIdentifier, projectIdentifier] = secretSpacePath.split('/')
|
||||||
return {
|
return {
|
||||||
|
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2024 Harness, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.tabsContainer {
|
||||||
|
position: relative !important;
|
||||||
|
& > :global(.bp3-tabs > .bp3-tab-list) {
|
||||||
|
border-bottom: 1px solid var(--grey-200);
|
||||||
|
}
|
||||||
|
:global {
|
||||||
|
.bp3-tab-panel {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bp3-tab-list {
|
||||||
|
background-color: var(--white);
|
||||||
|
width: 100%;
|
||||||
|
border-bottom: 0;
|
||||||
|
box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.13);
|
||||||
|
align-items: center;
|
||||||
|
padding: 0 var(--spacing-xlarge);
|
||||||
|
|
||||||
|
position: sticky;
|
||||||
|
top: 0px;
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
19
web/src/ar/pages/webhook-details/WebhookDetailsPage.module.scss.d.ts
vendored
Normal file
19
web/src/ar/pages/webhook-details/WebhookDetailsPage.module.scss.d.ts
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2023 Harness, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* eslint-disable */
|
||||||
|
// This is an auto-generated file
|
||||||
|
export declare const tabsContainer: string
|
128
web/src/ar/pages/webhook-details/WebhookDetailsPage.tsx
Normal file
128
web/src/ar/pages/webhook-details/WebhookDetailsPage.tsx
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2024 Harness, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React, { useState } from 'react'
|
||||||
|
import type { FormikProps } from 'formik'
|
||||||
|
import { Expander } from '@blueprintjs/core'
|
||||||
|
import { useGetWebhookQuery, type WebhookRequest } from '@harnessio/react-har-service-client'
|
||||||
|
import { Redirect, Switch, useHistory, useParams } from 'react-router-dom'
|
||||||
|
import { Button, ButtonVariation, Container, Layout, Page, Tab, Tabs } from '@harnessio/uicore'
|
||||||
|
|
||||||
|
import { useStrings } from '@ar/frameworks/strings'
|
||||||
|
import RouteProvider from '@ar/components/RouteProvider/RouteProvider'
|
||||||
|
import type { RepositoryWebhookDetailsPathParams } from '@ar/routes/types'
|
||||||
|
import { useGetSpaceRef, useParentComponents, useRoutes } from '@ar/hooks'
|
||||||
|
import { PermissionIdentifier, ResourceType } from '@ar/common/permissionTypes'
|
||||||
|
import { repositoryWebhookDetailsPathParams, repositoryWebhookDetailsTabPathParams } from '@ar/routes/RouteDestinations'
|
||||||
|
|
||||||
|
import { WebhookDetailsTab } from './constants'
|
||||||
|
import WebhookDetailsTabPage from './WebhookDetailsTabPage'
|
||||||
|
// import { MOCK_WEBHOK_LIST_TABLE } from '../webhook-list/mockData'
|
||||||
|
import { WebhookDetailsContext } from './context/WebhookDetailsContext'
|
||||||
|
import { WebhookDetailsPageHeader } from './components/WebhookDetailsPageHeader/WebhookDetailsPageHeader'
|
||||||
|
|
||||||
|
import css from './WebhookDetailsPage.module.scss'
|
||||||
|
|
||||||
|
export default function WebhookDetailsPage() {
|
||||||
|
const params = useParams<RepositoryWebhookDetailsPathParams>()
|
||||||
|
const { repositoryIdentifier, webhookIdentifier } = params
|
||||||
|
const history = useHistory()
|
||||||
|
const routes = useRoutes()
|
||||||
|
const routeDefinitions = useRoutes(true)
|
||||||
|
const { RbacButton } = useParentComponents()
|
||||||
|
|
||||||
|
const registryRef = useGetSpaceRef()
|
||||||
|
const { getString } = useStrings()
|
||||||
|
const stepRef = React.useRef<FormikProps<WebhookRequest> | null>(null)
|
||||||
|
|
||||||
|
const [activeTab, setActiveTab] = useState(WebhookDetailsTab.Configuration)
|
||||||
|
const [isDirty, setIsDirty] = useState(false)
|
||||||
|
const [isUpdating, setUpdating] = useState(false)
|
||||||
|
|
||||||
|
const { isFetching, error, data, refetch } = useGetWebhookQuery({
|
||||||
|
registry_ref: registryRef,
|
||||||
|
webhook_identifier: webhookIdentifier
|
||||||
|
})
|
||||||
|
|
||||||
|
const handleChangeTab = (nextTab: WebhookDetailsTab): void => {
|
||||||
|
setActiveTab(nextTab)
|
||||||
|
history.push(routes.toARRepositoryWebhookDetailsTab({ ...params, tab: nextTab }))
|
||||||
|
}
|
||||||
|
|
||||||
|
const renderActionBtns = (): JSX.Element => (
|
||||||
|
<Layout.Horizontal spacing="medium">
|
||||||
|
<RbacButton
|
||||||
|
text={getString('save')}
|
||||||
|
variation={ButtonVariation.PRIMARY}
|
||||||
|
onClick={stepRef.current?.submitForm}
|
||||||
|
disabled={!isDirty || isUpdating}
|
||||||
|
permission={{
|
||||||
|
permission: PermissionIdentifier.EDIT_ARTIFACT_REGISTRY,
|
||||||
|
resource: {
|
||||||
|
resourceType: ResourceType.ARTIFACT_REGISTRY,
|
||||||
|
resourceIdentifier: repositoryIdentifier
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
variation={ButtonVariation.SECONDARY}
|
||||||
|
text={getString('discard')}
|
||||||
|
onClick={() => stepRef.current?.resetForm()}
|
||||||
|
disabled={!isDirty}
|
||||||
|
/>
|
||||||
|
</Layout.Horizontal>
|
||||||
|
)
|
||||||
|
|
||||||
|
const response = data?.content.data
|
||||||
|
// const response = MOCK_WEBHOK_LIST_TABLE.webhooks[0]
|
||||||
|
|
||||||
|
return (
|
||||||
|
<WebhookDetailsContext.Provider value={{ data: response, loading: isFetching, setDirty: setIsDirty, setUpdating }}>
|
||||||
|
<Page.Body loading={isFetching} error={error} retryOnError={() => refetch()}>
|
||||||
|
{response && !isFetching && (
|
||||||
|
<Container>
|
||||||
|
<WebhookDetailsPageHeader data={response} repositoryIdentifier={repositoryIdentifier} />
|
||||||
|
<Container className={css.tabsContainer}>
|
||||||
|
<Tabs id="webhookDetailsTabs" selectedTabId={activeTab} onChange={handleChangeTab}>
|
||||||
|
<Tab id={WebhookDetailsTab.Configuration} title={getString('webhookDetails.tabs.configuration')} />
|
||||||
|
<Tab id={WebhookDetailsTab.Executions} title={getString('webhookDetails.tabs.executions')} />
|
||||||
|
<Expander />
|
||||||
|
{activeTab === WebhookDetailsTab.Configuration && renderActionBtns()}
|
||||||
|
</Tabs>
|
||||||
|
</Container>
|
||||||
|
<Switch>
|
||||||
|
<RouteProvider
|
||||||
|
exact
|
||||||
|
path={routeDefinitions.toARRepositoryWebhookDetails({ ...repositoryWebhookDetailsPathParams })}>
|
||||||
|
<Redirect
|
||||||
|
to={routes.toARRepositoryWebhookDetailsTab({
|
||||||
|
...params,
|
||||||
|
tab: WebhookDetailsTab.Configuration
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
</RouteProvider>
|
||||||
|
<RouteProvider
|
||||||
|
exact
|
||||||
|
path={routeDefinitions.toARRepositoryWebhookDetailsTab({ ...repositoryWebhookDetailsTabPathParams })}>
|
||||||
|
<WebhookDetailsTabPage onInit={setActiveTab} formRef={stepRef} />
|
||||||
|
</RouteProvider>
|
||||||
|
</Switch>
|
||||||
|
</Container>
|
||||||
|
)}
|
||||||
|
</Page.Body>
|
||||||
|
</WebhookDetailsContext.Provider>
|
||||||
|
)
|
||||||
|
}
|
49
web/src/ar/pages/webhook-details/WebhookDetailsTabPage.tsx
Normal file
49
web/src/ar/pages/webhook-details/WebhookDetailsTabPage.tsx
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2024 Harness, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React, { useEffect } from 'react'
|
||||||
|
import type { FormikProps } from 'formik'
|
||||||
|
import { useParams } from 'react-router-dom'
|
||||||
|
import type { WebhookRequest } from '@harnessio/react-har-service-client'
|
||||||
|
|
||||||
|
import type { RepositoryWebhookDetailsTabPathParams } from '@ar/routes/types'
|
||||||
|
|
||||||
|
import { WebhookDetailsTab } from './constants'
|
||||||
|
import WebhookConfigurationForm from './components/WebhookConfigurationForm/WebhookConfigurationForm'
|
||||||
|
|
||||||
|
interface WebhookDetailsTabPageProps {
|
||||||
|
onInit: (tab: WebhookDetailsTab) => void
|
||||||
|
formRef: React.RefObject<FormikProps<WebhookRequest>>
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function WebhookDetailsTabPage(props: WebhookDetailsTabPageProps): JSX.Element {
|
||||||
|
const { onInit, formRef } = props
|
||||||
|
const params = useParams<RepositoryWebhookDetailsTabPathParams>()
|
||||||
|
const { tab } = params
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
onInit(tab)
|
||||||
|
}, [tab])
|
||||||
|
|
||||||
|
switch (tab) {
|
||||||
|
case WebhookDetailsTab.Configuration:
|
||||||
|
return <WebhookConfigurationForm formRef={formRef} />
|
||||||
|
case WebhookDetailsTab.Executions:
|
||||||
|
return <>Executions Page</>
|
||||||
|
default:
|
||||||
|
return <>Not Found</>
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2024 Harness, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.formContainer {
|
||||||
|
:global(.bp3-form-group .bp3-input),
|
||||||
|
:global(.bp3-form-group .bp3-input-group),
|
||||||
|
:global(.bp3-form-group .bp3-select-popover) {
|
||||||
|
width: var(--input-element-width);
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.bp3-form-group.bp3-inline .bp3-input),
|
||||||
|
:global(.bp3-form-group.bp3-inline .bp3-input-group),
|
||||||
|
:global(.bp3-form-group.bp3-inline .bp3-select-popover) {
|
||||||
|
width: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
div[class*='InputWithIdentifier--txtNameContainer-'] {
|
||||||
|
width: var(--input-element-width);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2023 Harness, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* eslint-disable */
|
||||||
|
// This is an auto-generated file
|
||||||
|
export declare const formContainer: string
|
@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2024 Harness, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React, { useContext } from 'react'
|
||||||
|
import type { FormikProps } from 'formik'
|
||||||
|
import { useParams } from 'react-router-dom'
|
||||||
|
import { updateWebhook, WebhookRequest } from '@harnessio/react-har-service-client'
|
||||||
|
import { Container, getErrorInfoFromErrorObject, useToaster } from '@harnessio/uicore'
|
||||||
|
|
||||||
|
import { useGetSpaceRef } from '@ar/hooks'
|
||||||
|
import { queryClient } from '@ar/utils/queryClient'
|
||||||
|
import { useStrings } from '@ar/frameworks/strings'
|
||||||
|
import WebhookForm from '@ar/pages/webhook-list/components/Forms/WebhookForm'
|
||||||
|
import type { RepositoryWebhookDetailsTabPathParams } from '@ar/routes/types'
|
||||||
|
|
||||||
|
import { WebhookDetailsContext } from '../../context/WebhookDetailsContext'
|
||||||
|
import css from './WebhookConfigurationForm.module.scss'
|
||||||
|
|
||||||
|
interface WebhookConfigurationFormProps {
|
||||||
|
formRef: React.RefObject<FormikProps<WebhookRequest>>
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function WebhookConfigurationForm(props: WebhookConfigurationFormProps): JSX.Element {
|
||||||
|
const { formRef } = props
|
||||||
|
const { showError, showSuccess, clear } = useToaster()
|
||||||
|
const { getString } = useStrings()
|
||||||
|
|
||||||
|
const { data, setDirty, setUpdating } = useContext(WebhookDetailsContext)
|
||||||
|
const registryRef = useGetSpaceRef()
|
||||||
|
const { webhookIdentifier } = useParams<RepositoryWebhookDetailsTabPathParams>()
|
||||||
|
|
||||||
|
const handleUpdateWebhook = async (values: WebhookRequest) => {
|
||||||
|
try {
|
||||||
|
setUpdating?.(true)
|
||||||
|
await updateWebhook({
|
||||||
|
registry_ref: registryRef,
|
||||||
|
webhook_identifier: webhookIdentifier,
|
||||||
|
body: values
|
||||||
|
})
|
||||||
|
showSuccess(getString('webhookList.webhookUpdated'))
|
||||||
|
queryClient.invalidateQueries(['GetWebhook'])
|
||||||
|
} catch (e) {
|
||||||
|
clear()
|
||||||
|
showError(getErrorInfoFromErrorObject(e as Error))
|
||||||
|
} finally {
|
||||||
|
setUpdating?.(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!data) return <></>
|
||||||
|
return (
|
||||||
|
<Container className={css.formContainer} padding="xlarge">
|
||||||
|
<WebhookForm data={data} ref={formRef} isEdit onSubmit={handleUpdateWebhook} setDirty={setDirty} />
|
||||||
|
</Container>
|
||||||
|
)
|
||||||
|
}
|
@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2024 Harness, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from 'react'
|
||||||
|
import { Page, Text } from '@harnessio/uicore'
|
||||||
|
import { FontVariation } from '@harnessio/design-system'
|
||||||
|
import type { Webhook } from '@harnessio/react-har-service-client'
|
||||||
|
|
||||||
|
import { useStrings } from '@ar/frameworks/strings'
|
||||||
|
import { useParentComponents, useRoutes } from '@ar/hooks'
|
||||||
|
import { getIdentifierStringForBreadcrumb } from '@ar/common/utils'
|
||||||
|
import { RepositoryDetailsTab } from '@ar/pages/repository-details/constants'
|
||||||
|
|
||||||
|
interface WebhookDetailsPageHeaderProps {
|
||||||
|
data: Webhook
|
||||||
|
repositoryIdentifier: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export function WebhookDetailsPageHeader(props: WebhookDetailsPageHeaderProps) {
|
||||||
|
const { data, repositoryIdentifier } = props
|
||||||
|
const { NGBreadcrumbs } = useParentComponents()
|
||||||
|
const routes = useRoutes()
|
||||||
|
const { getString } = useStrings()
|
||||||
|
return (
|
||||||
|
<Page.Header
|
||||||
|
title={
|
||||||
|
<Text font={{ variation: FontVariation.H4 }} lineClamp={1}>
|
||||||
|
{data.name}
|
||||||
|
</Text>
|
||||||
|
}
|
||||||
|
size="large"
|
||||||
|
breadcrumbs={
|
||||||
|
<NGBreadcrumbs
|
||||||
|
links={[
|
||||||
|
{
|
||||||
|
url: routes.toARRepositories(),
|
||||||
|
label: getString('breadcrumbs.repositories')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: routes.toARRepositoryDetailsTab({
|
||||||
|
repositoryIdentifier,
|
||||||
|
tab: RepositoryDetailsTab.WEBHOOKS
|
||||||
|
}),
|
||||||
|
label: getIdentifierStringForBreadcrumb(getString('breadcrumbs.repositories'), repositoryIdentifier)
|
||||||
|
}
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
20
web/src/ar/pages/webhook-details/constants.tsx
Normal file
20
web/src/ar/pages/webhook-details/constants.tsx
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2024 Harness, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export enum WebhookDetailsTab {
|
||||||
|
Configuration = 'configuration',
|
||||||
|
Executions = 'executions'
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2024 Harness, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { createContext } from 'react'
|
||||||
|
import type { Webhook } from '@harnessio/react-har-service-client'
|
||||||
|
|
||||||
|
interface WebhookDetailsContextSpec {
|
||||||
|
data?: Webhook
|
||||||
|
loading?: boolean
|
||||||
|
setDirty?: (dirty: boolean) => void
|
||||||
|
setUpdating?: (updating: boolean) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export const WebhookDetailsContext = createContext<WebhookDetailsContextSpec>({
|
||||||
|
data: {} as Webhook,
|
||||||
|
loading: false
|
||||||
|
})
|
3
web/src/ar/pages/webhook-details/strings/strings.en.yaml
Normal file
3
web/src/ar/pages/webhook-details/strings/strings.en.yaml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
tabs:
|
||||||
|
configuration: Configuration
|
||||||
|
executions: Executions
|
@ -17,7 +17,7 @@
|
|||||||
import React, { forwardRef, useMemo } from 'react'
|
import React, { forwardRef, useMemo } from 'react'
|
||||||
import * as Yup from 'yup'
|
import * as Yup from 'yup'
|
||||||
import { Formik } from '@harnessio/uicore'
|
import { Formik } from '@harnessio/uicore'
|
||||||
import type { WebhookRequest } from '@harnessio/react-har-service-client'
|
import type { Webhook, WebhookRequest } from '@harnessio/react-har-service-client'
|
||||||
|
|
||||||
import { useAppStore } from '@ar/hooks'
|
import { useAppStore } from '@ar/hooks'
|
||||||
import { GENERIC_URL_REGEX } from '@ar/constants'
|
import { GENERIC_URL_REGEX } from '@ar/constants'
|
||||||
@ -27,19 +27,24 @@ import type { FormikFowardRef } from '@ar/common/types'
|
|||||||
|
|
||||||
import type { WebhookRequestUI } from './types'
|
import type { WebhookRequestUI } from './types'
|
||||||
import WebhookFormContent from './WebhookFormContent'
|
import WebhookFormContent from './WebhookFormContent'
|
||||||
import { transformFormValuesToSubmitValues } from './utils'
|
import { transformFormValuesToSubmitValues, transformWebhookDataToFormValues } from './utils'
|
||||||
|
|
||||||
interface CreateWebhookFormProps {
|
interface CreateWebhookFormProps {
|
||||||
|
data?: Webhook
|
||||||
onSubmit: (values: WebhookRequest) => void
|
onSubmit: (values: WebhookRequest) => void
|
||||||
|
setDirty?: (dirty: boolean) => void
|
||||||
readonly?: boolean
|
readonly?: boolean
|
||||||
isEdit?: boolean
|
isEdit?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
function WebhookForm(props: CreateWebhookFormProps, formikRef: FormikFowardRef<WebhookRequestUI>) {
|
function WebhookForm(props: CreateWebhookFormProps, formikRef: FormikFowardRef<WebhookRequestUI>) {
|
||||||
const { onSubmit, readonly, isEdit } = props
|
const { onSubmit, readonly, isEdit, data, setDirty } = props
|
||||||
const { getString } = useStrings()
|
const { getString } = useStrings()
|
||||||
const { parent, scope } = useAppStore()
|
const { parent, scope } = useAppStore()
|
||||||
const initialValues: WebhookRequestUI = useMemo(() => {
|
const initialValues: WebhookRequestUI = useMemo(() => {
|
||||||
|
if (isEdit && data) {
|
||||||
|
return transformWebhookDataToFormValues(data, parent)
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
identifier: '',
|
identifier: '',
|
||||||
name: '',
|
name: '',
|
||||||
@ -74,6 +79,7 @@ function WebhookForm(props: CreateWebhookFormProps, formikRef: FormikFowardRef<W
|
|||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
initialValues={initialValues}>
|
initialValues={initialValues}>
|
||||||
{formik => {
|
{formik => {
|
||||||
|
setDirty?.(formik.dirty)
|
||||||
setFormikRef(formikRef, formik)
|
setFormikRef(formikRef, formik)
|
||||||
return <WebhookFormContent formikProps={formik} isEdit={isEdit} readonly={readonly} />
|
return <WebhookFormContent formikProps={formik} isEdit={isEdit} readonly={readonly} />
|
||||||
}}
|
}}
|
||||||
|
@ -16,11 +16,14 @@
|
|||||||
|
|
||||||
import produce from 'immer'
|
import produce from 'immer'
|
||||||
import { get, set } from 'lodash-es'
|
import { get, set } from 'lodash-es'
|
||||||
import type { WebhookRequest } from '@harnessio/react-har-service-client'
|
import type { WebhookRequest, Webhook } from '@harnessio/react-har-service-client'
|
||||||
|
|
||||||
import type { Scope } from '@ar/MFEAppTypes'
|
import type { Scope } from '@ar/MFEAppTypes'
|
||||||
import { Parent } from '@ar/common/types'
|
import { Parent } from '@ar/common/types'
|
||||||
import { getSecretSpacePath } from '@ar/pages/upstream-proxy-details/components/Forms/utils'
|
import {
|
||||||
|
getSecretScopeDetailsByIdentifier,
|
||||||
|
getSecretSpacePath
|
||||||
|
} from '@ar/pages/upstream-proxy-details/components/Forms/utils'
|
||||||
|
|
||||||
import type { WebhookRequestUI } from './types'
|
import type { WebhookRequestUI } from './types'
|
||||||
|
|
||||||
@ -54,3 +57,26 @@ export function transformFormValuesToSubmitValues(
|
|||||||
return draft
|
return draft
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function convertFormFieldsToSecreteInput(formData: Webhook, secretField: string, secretSpacePathField: string) {
|
||||||
|
const secretIdentifier = get(formData, secretField, '')
|
||||||
|
const secretSpacePath = get(formData, secretSpacePathField, '')
|
||||||
|
set(formData, secretField, getSecretScopeDetailsByIdentifier(secretIdentifier, secretSpacePath))
|
||||||
|
}
|
||||||
|
|
||||||
|
export function transformWebhookDataToFormValues(data: Webhook, parent: Parent): WebhookRequestUI {
|
||||||
|
return produce(data, draft => {
|
||||||
|
if (draft.triggers?.length) {
|
||||||
|
set(draft, 'triggerType', 'custom')
|
||||||
|
} else {
|
||||||
|
set(draft, 'triggerType', 'all')
|
||||||
|
}
|
||||||
|
if (!draft.extraHeaders?.length) {
|
||||||
|
set(draft, 'extraHeaders', [{ key: '', value: '' }])
|
||||||
|
}
|
||||||
|
if (parent === Parent.Enterprise) {
|
||||||
|
convertFormFieldsToSecreteInput(draft, 'secretIdentifier', 'secretSpacePath')
|
||||||
|
}
|
||||||
|
return draft
|
||||||
|
}) as WebhookRequestUI
|
||||||
|
}
|
||||||
|
@ -17,12 +17,13 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import classNames from 'classnames'
|
import classNames from 'classnames'
|
||||||
import type { Column } from 'react-table'
|
import type { Column } from 'react-table'
|
||||||
import { useHistory } from 'react-router-dom'
|
import { useHistory, useParams } from 'react-router-dom'
|
||||||
import { type PaginationProps, TableV2 } from '@harnessio/uicore'
|
import { type PaginationProps, TableV2 } from '@harnessio/uicore'
|
||||||
import type { ListWebhooks, Webhook } from '@harnessio/react-har-service-client'
|
import type { ListWebhooks, Webhook } from '@harnessio/react-har-service-client'
|
||||||
|
|
||||||
import { useStrings } from '@ar/frameworks/strings'
|
import { useStrings } from '@ar/frameworks/strings'
|
||||||
import { useParentHooks, useRoutes } from '@ar/hooks'
|
import { useParentHooks, useRoutes } from '@ar/hooks'
|
||||||
|
import type { RepositoryDetailsTabPathParams } from '@ar/routes/types'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
WebhookActionsCell,
|
WebhookActionsCell,
|
||||||
@ -50,6 +51,7 @@ export interface WebhookListTableProps extends WebhookListColumnActions {
|
|||||||
export default function WebhookListTable(props: WebhookListTableProps): JSX.Element {
|
export default function WebhookListTable(props: WebhookListTableProps): JSX.Element {
|
||||||
const { data, gotoPage, onPageSizeChange, readonly, sortBy, setSortBy } = props
|
const { data, gotoPage, onPageSizeChange, readonly, sortBy, setSortBy } = props
|
||||||
const { useDefaultPaginationProps } = useParentHooks()
|
const { useDefaultPaginationProps } = useParentHooks()
|
||||||
|
const { repositoryIdentifier } = useParams<RepositoryDetailsTabPathParams>()
|
||||||
const { getString } = useStrings()
|
const { getString } = useStrings()
|
||||||
const history = useHistory()
|
const history = useHistory()
|
||||||
const routes = useRoutes()
|
const routes = useRoutes()
|
||||||
@ -116,7 +118,7 @@ export default function WebhookListTable(props: WebhookListTableProps): JSX.Elem
|
|||||||
onRowClick={rowDetails => {
|
onRowClick={rowDetails => {
|
||||||
history.push(
|
history.push(
|
||||||
routes.toARRepositoryWebhookDetails({
|
routes.toARRepositoryWebhookDetails({
|
||||||
repositoryIdentifier: rowDetails.identifier,
|
repositoryIdentifier,
|
||||||
webhookIdentifier: rowDetails.identifier
|
webhookIdentifier: rowDetails.identifier
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
newWebhook: New Webhook
|
newWebhook: New Webhook
|
||||||
webhookCreated: Webhook created successfully
|
webhookCreated: Webhook created successfully
|
||||||
|
webhookUpdated: Webhook updated successfully
|
||||||
triggers:
|
triggers:
|
||||||
artifactCreation: 'Artifact Creation'
|
artifactCreation: 'Artifact Creation'
|
||||||
artifactDeletion: 'Artifact Deletion'
|
artifactDeletion: 'Artifact Deletion'
|
||||||
|
@ -21,6 +21,7 @@ import type {
|
|||||||
RepositoryDetailsPathParams,
|
RepositoryDetailsPathParams,
|
||||||
RepositoryDetailsTabPathParams,
|
RepositoryDetailsTabPathParams,
|
||||||
RepositoryWebhookDetailsPathParams,
|
RepositoryWebhookDetailsPathParams,
|
||||||
|
RepositoryWebhookDetailsTabPathParams,
|
||||||
VersionDetailsPathParams,
|
VersionDetailsPathParams,
|
||||||
VersionDetailsTabPathParams
|
VersionDetailsTabPathParams
|
||||||
} from './types'
|
} from './types'
|
||||||
@ -36,6 +37,7 @@ export interface ARRouteDefinitionsReturn {
|
|||||||
toARVersionDetails: (params: VersionDetailsPathParams) => string
|
toARVersionDetails: (params: VersionDetailsPathParams) => string
|
||||||
toARVersionDetailsTab: (params: VersionDetailsTabPathParams) => string
|
toARVersionDetailsTab: (params: VersionDetailsTabPathParams) => string
|
||||||
toARRepositoryWebhookDetails: (params: RepositoryWebhookDetailsPathParams) => string
|
toARRepositoryWebhookDetails: (params: RepositoryWebhookDetailsPathParams) => string
|
||||||
|
toARRepositoryWebhookDetailsTab: (params: RepositoryWebhookDetailsTabPathParams) => string
|
||||||
}
|
}
|
||||||
|
|
||||||
export const routeDefinitions: ARRouteDefinitionsReturn = {
|
export const routeDefinitions: ARRouteDefinitionsReturn = {
|
||||||
@ -70,5 +72,7 @@ export const routeDefinitions: ARRouteDefinitionsReturn = {
|
|||||||
return `/registries/${params?.repositoryIdentifier}/artifacts/${params?.artifactIdentifier}/versions/${params?.versionIdentifier}/${params.versionTab}`
|
return `/registries/${params?.repositoryIdentifier}/artifacts/${params?.artifactIdentifier}/versions/${params?.versionIdentifier}/${params.versionTab}`
|
||||||
},
|
},
|
||||||
toARRepositoryWebhookDetails: params =>
|
toARRepositoryWebhookDetails: params =>
|
||||||
`/registries/${params?.repositoryIdentifier}/webhooks/${params?.webhookIdentifier}`
|
`/registries/${params?.repositoryIdentifier}/webhooks/${params?.webhookIdentifier}`,
|
||||||
|
toARRepositoryWebhookDetailsTab: params =>
|
||||||
|
`/registries/${params?.repositoryIdentifier}/webhooks/${params?.webhookIdentifier}/${params.tab}`
|
||||||
}
|
}
|
||||||
|
@ -20,12 +20,15 @@ import { Redirect, Switch } from 'react-router-dom'
|
|||||||
import { Parent } from '@ar/common/types'
|
import { Parent } from '@ar/common/types'
|
||||||
import { useAppStore, useRoutes } from '@ar/hooks'
|
import { useAppStore, useRoutes } from '@ar/hooks'
|
||||||
import RedirectPage from '@ar/pages/redirect-page/RedirectPage'
|
import RedirectPage from '@ar/pages/redirect-page/RedirectPage'
|
||||||
|
import type { WebhookDetailsTab } from '@ar/pages/webhook-details/constants'
|
||||||
import type { RepositoryDetailsTab } from '@ar/pages/repository-details/constants'
|
import type { RepositoryDetailsTab } from '@ar/pages/repository-details/constants'
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
ArtifactDetailsPathParams,
|
ArtifactDetailsPathParams,
|
||||||
RepositoryDetailsPathParams,
|
RepositoryDetailsPathParams,
|
||||||
RepositoryDetailsTabPathParams,
|
RepositoryDetailsTabPathParams,
|
||||||
|
RepositoryWebhookDetailsPathParams,
|
||||||
|
RepositoryWebhookDetailsTabPathParams,
|
||||||
VersionDetailsPathParams,
|
VersionDetailsPathParams,
|
||||||
VersionDetailsTabPathParams
|
VersionDetailsTabPathParams
|
||||||
} from './types'
|
} from './types'
|
||||||
@ -37,6 +40,7 @@ const ArtifactDetailsPage = React.lazy(() => import('@ar/pages/artifact-details/
|
|||||||
const VersionDetailsPage = React.lazy(() => import('@ar/pages/version-details/VersionDetailsPage'))
|
const VersionDetailsPage = React.lazy(() => import('@ar/pages/version-details/VersionDetailsPage'))
|
||||||
const OSSVersionDetailsPage = React.lazy(() => import('@ar/pages/version-details/OSSVersionDetailsPage'))
|
const OSSVersionDetailsPage = React.lazy(() => import('@ar/pages/version-details/OSSVersionDetailsPage'))
|
||||||
const RouteProvider = React.lazy(() => import('@ar/components/RouteProvider/RouteProvider'))
|
const RouteProvider = React.lazy(() => import('@ar/components/RouteProvider/RouteProvider'))
|
||||||
|
const WebhookDetailsPage = React.lazy(() => import('@ar/pages/webhook-details/WebhookDetailsPage'))
|
||||||
|
|
||||||
export const repositoryDetailsPathProps: RepositoryDetailsPathParams = {
|
export const repositoryDetailsPathProps: RepositoryDetailsPathParams = {
|
||||||
repositoryIdentifier: ':repositoryIdentifier'
|
repositoryIdentifier: ':repositoryIdentifier'
|
||||||
@ -74,6 +78,16 @@ export const versionDetailsTabWithSSCADetailsPathParams: VersionDetailsTabPathPa
|
|||||||
artifactId: ':artifactId'
|
artifactId: ':artifactId'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const repositoryWebhookDetailsPathParams: RepositoryWebhookDetailsPathParams = {
|
||||||
|
...repositoryDetailsPathProps,
|
||||||
|
webhookIdentifier: ':webhookIdentifier'
|
||||||
|
}
|
||||||
|
|
||||||
|
export const repositoryWebhookDetailsTabPathParams: RepositoryWebhookDetailsTabPathParams = {
|
||||||
|
...repositoryWebhookDetailsPathParams,
|
||||||
|
tab: ':tab' as WebhookDetailsTab
|
||||||
|
}
|
||||||
|
|
||||||
const RouteDestinations = (): JSX.Element => {
|
const RouteDestinations = (): JSX.Element => {
|
||||||
const routes = useRoutes(true)
|
const routes = useRoutes(true)
|
||||||
const { parent } = useAppStore()
|
const { parent } = useAppStore()
|
||||||
@ -110,6 +124,9 @@ const RouteDestinations = (): JSX.Element => {
|
|||||||
<VersionDetailsPage />
|
<VersionDetailsPage />
|
||||||
</RouteProvider>
|
</RouteProvider>
|
||||||
)}
|
)}
|
||||||
|
<RouteProvider path={routes.toARRepositoryWebhookDetails({ ...repositoryWebhookDetailsPathParams })}>
|
||||||
|
<WebhookDetailsPage />
|
||||||
|
</RouteProvider>
|
||||||
<RouteProvider path={routes.toARRepositoryDetails({ ...repositoryDetailsPathProps })}>
|
<RouteProvider path={routes.toARRepositoryDetails({ ...repositoryDetailsPathProps })}>
|
||||||
<RepositoryDetailsPage />
|
<RepositoryDetailsPage />
|
||||||
</RouteProvider>
|
</RouteProvider>
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
import type { RepositoryPackageType } from '@ar/common/types'
|
import type { RepositoryPackageType } from '@ar/common/types'
|
||||||
import type { RepositoryDetailsTab } from '@ar/pages/repository-details/constants'
|
import type { RepositoryDetailsTab } from '@ar/pages/repository-details/constants'
|
||||||
import type { VersionDetailsTab } from '@ar/pages/version-details/components/VersionDetailsTabs/constants'
|
import type { VersionDetailsTab } from '@ar/pages/version-details/components/VersionDetailsTabs/constants'
|
||||||
|
import type { WebhookDetailsTab } from '@ar/pages/webhook-details/constants'
|
||||||
|
|
||||||
export interface RepositoryDetailsPathParams {
|
export interface RepositoryDetailsPathParams {
|
||||||
repositoryIdentifier: string
|
repositoryIdentifier: string
|
||||||
@ -56,3 +57,7 @@ export interface RedirectPageQueryParams {
|
|||||||
export interface RepositoryWebhookDetailsPathParams extends RepositoryDetailsPathParams {
|
export interface RepositoryWebhookDetailsPathParams extends RepositoryDetailsPathParams {
|
||||||
webhookIdentifier: string
|
webhookIdentifier: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface RepositoryWebhookDetailsTabPathParams extends RepositoryWebhookDetailsPathParams {
|
||||||
|
tab: WebhookDetailsTab
|
||||||
|
}
|
||||||
|
@ -229,6 +229,8 @@ export interface StringsMap {
|
|||||||
'versionList.table.columns.size': string
|
'versionList.table.columns.size': string
|
||||||
'versionList.table.columns.version': string
|
'versionList.table.columns.version': string
|
||||||
'versionList.table.noVersionsTitle': string
|
'versionList.table.noVersionsTitle': string
|
||||||
|
'webhookDetails.tabs.configuration': string
|
||||||
|
'webhookDetails.tabs.executions': string
|
||||||
'webhookList.formFields.SSLVerification': string
|
'webhookList.formFields.SSLVerification': string
|
||||||
'webhookList.formFields.addNewKeyValuePair': string
|
'webhookList.formFields.addNewKeyValuePair': string
|
||||||
'webhookList.formFields.advanced': string
|
'webhookList.formFields.advanced': string
|
||||||
@ -254,6 +256,7 @@ export interface StringsMap {
|
|||||||
'webhookList.triggers.artifactDeletion': string
|
'webhookList.triggers.artifactDeletion': string
|
||||||
'webhookList.triggers.artifactModification': string
|
'webhookList.triggers.artifactModification': string
|
||||||
'webhookList.webhookCreated': string
|
'webhookList.webhookCreated': string
|
||||||
|
'webhookList.webhookUpdated': string
|
||||||
'actions.delete': string
|
'actions.delete': string
|
||||||
'actions.edit': string
|
'actions.edit': string
|
||||||
'actions.quarantine': string
|
'actions.quarantine': string
|
||||||
|
Loading…
Reference in New Issue
Block a user