diff --git a/web/package.json b/web/package.json index fb46fce4b..50f9b267a 100644 --- a/web/package.json +++ b/web/package.json @@ -51,7 +51,7 @@ "@codemirror/view": "^6.9.6", "@harnessio/design-system": "^2.1.1", "@harnessio/icons": "^2.1.9", - "@harnessio/react-har-service-client": "^0.4.0", + "@harnessio/react-har-service-client": "^0.6.0", "@harnessio/react-ssca-manager-client": "^0.65.0", "@harnessio/uicore": "^4.1.2", "@tanstack/react-query": "4.20.4", diff --git a/web/src/ar/frameworks/strings/languageLoader.ts b/web/src/ar/frameworks/strings/languageLoader.ts index b0e80e413..8b010c885 100644 --- a/web/src/ar/frameworks/strings/languageLoader.ts +++ b/web/src/ar/frameworks/strings/languageLoader.ts @@ -27,6 +27,7 @@ import repositoryList from '@ar/pages/repository-list/strings/strings.en.yaml' import upstreamProxyDetails from '@ar/pages/upstream-proxy-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 webhookList from '@ar/pages/webhook-list/strings/strings.en.yaml' export default function languageLoader() { return { @@ -37,6 +38,7 @@ export default function languageLoader() { repositoryList, upstreamProxyDetails, versionDetails, - versionList + versionList, + webhookList } } diff --git a/web/src/ar/pages/repository-details/RepositoryDetailsTabPage.tsx b/web/src/ar/pages/repository-details/RepositoryDetailsTabPage.tsx index 1d5e35ec6..5abf836bf 100644 --- a/web/src/ar/pages/repository-details/RepositoryDetailsTabPage.tsx +++ b/web/src/ar/pages/repository-details/RepositoryDetailsTabPage.tsx @@ -26,6 +26,7 @@ import type { RepositoryConfigType, RepositoryPackageType } from '@ar/common/typ import RepositoryConfigurationFormWidget from '@ar/frameworks/RepositoryStep/RepositoryConfigurationFormWidget' import { RepositoryDetailsTab } from './constants' +import WebhookListPage from '../webhook-list/WebhookListPage' import { RepositoryProviderContext } from './context/RepositoryProvider' import RegistryArtifactListPage from '../artifact-list/RegistryArtifactListPage' @@ -58,6 +59,8 @@ export default function RepositoryDetailsTabPage(props: RepositoryDetailsTabPage readonly={isReadonly} /> ) + case RepositoryDetailsTab.WEBHOOKS: + return default: return {getString('stepNotFound')} } diff --git a/web/src/ar/pages/webhook-list/WebhookListPage.module.scss b/web/src/ar/pages/webhook-list/WebhookListPage.module.scss new file mode 100644 index 000000000..04d0a82eb --- /dev/null +++ b/web/src/ar/pages/webhook-list/WebhookListPage.module.scss @@ -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. + */ + +.pageBody { + --page-header-height: 253px; + background-color: var(--primary-bg) !important; +} diff --git a/web/src/ar/pages/webhook-list/WebhookListPage.module.scss.d.ts b/web/src/ar/pages/webhook-list/WebhookListPage.module.scss.d.ts new file mode 100644 index 000000000..ed71a64c0 --- /dev/null +++ b/web/src/ar/pages/webhook-list/WebhookListPage.module.scss.d.ts @@ -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 pageBody: string diff --git a/web/src/ar/pages/webhook-list/WebhookListPage.tsx b/web/src/ar/pages/webhook-list/WebhookListPage.tsx new file mode 100644 index 000000000..9176bb835 --- /dev/null +++ b/web/src/ar/pages/webhook-list/WebhookListPage.tsx @@ -0,0 +1,151 @@ +/* + * 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, { useMemo, useRef } from 'react' +import { flushSync } from 'react-dom' +import { useParams } from 'react-router-dom' +import { Expander } from '@blueprintjs/core' +import { useListWebhooksQuery } from '@harnessio/react-har-service-client' +import { Button, ButtonVariation, ExpandingSearchInput, ExpandingSearchInputHandle, Page } from '@harnessio/uicore' + +import { DEFAULT_PAGE_INDEX, PreferenceScope } from '@ar/constants' +import { useStrings } from '@ar/frameworks/strings' +import type { RepositoryDetailsTabPathParams } from '@ar/routes/types' +import { useAppStore, useGetSpaceRef, useParentHooks } from '@ar/hooks' +import { PermissionIdentifier, ResourceType } from '@ar/common/permissionTypes' + +import WebhookListTable from './components/WebhookListTable/WebhookListTable' +import CreateWebhookButton from './components/CreateWebhookButton/CreateWebhookButton' +import { useListWebhooksQueryParamOptions, type WebhookListPageQueryParams } from './utils' + +import css from './WebhookListPage.module.scss' + +export default function WebhookListPage() { + const { getString } = useStrings() + const registryRef = useGetSpaceRef() + const searchRef = useRef({} as ExpandingSearchInputHandle) + + const { scope } = useAppStore() + const { repositoryIdentifier } = useParams() + const { useQueryParams, useUpdateQueryParams, usePermission, usePreferenceStore } = useParentHooks() + const { updateQueryParams } = useUpdateQueryParams>() + + const queryParamOptions = useListWebhooksQueryParamOptions() + const queryParams = useQueryParams(queryParamOptions) + + const { page, size, searchTerm } = queryParams + const { accountId, orgIdentifier, projectIdentifier } = scope + + const { preference: sortingPreference, setPreference: setSortingPreference } = usePreferenceStore( + PreferenceScope.USER, + 'ArtifactWebhooksSortingPreference' + ) + const sort = useMemo( + () => (sortingPreference ? JSON.parse(sortingPreference) : queryParams.sort), + [queryParams.sort, sortingPreference] + ) + + const [sortField, sortOrder] = sort || [] + + const [isEdit] = usePermission( + { + resourceScope: { + accountIdentifier: accountId, + orgIdentifier, + projectIdentifier + }, + resource: { + resourceType: ResourceType.ARTIFACT_REGISTRY, + resourceIdentifier: repositoryIdentifier + }, + permissions: [PermissionIdentifier.EDIT_ARTIFACT_REGISTRY] + }, + [accountId, projectIdentifier, orgIdentifier, repositoryIdentifier] + ) + + const { isFetching, data, error, refetch } = useListWebhooksQuery({ + registry_ref: registryRef, + queryParams: { + page, + size, + search_term: searchTerm, + sort_field: sortField, + sort_order: sortOrder + } + }) + + const handleClearFilters = (): void => { + flushSync(searchRef.current.clear) + updateQueryParams({ + page: undefined, + size: undefined, + searchTerm: undefined + }) + } + + const response = data?.content.data + + const hasFilter = !!searchTerm + return ( + <> + + + + { + updateQueryParams({ searchTerm: text || undefined, page: DEFAULT_PAGE_INDEX }) + }} + /> + + refetch()} + noData={{ + when: () => !response?.itemCount, + icon: 'code-webhook', + noIconColor: true, + messageTitle: hasFilter ? getString('noResultsFound') : getString('webhookList.table.noWebhooksTitle'), + button: hasFilter ? ( + + ) +} diff --git a/web/src/ar/pages/webhook-list/components/WebhookListTable/WebhookListTable.module.scss b/web/src/ar/pages/webhook-list/components/WebhookListTable/WebhookListTable.module.scss new file mode 100644 index 000000000..0947a6315 --- /dev/null +++ b/web/src/ar/pages/webhook-list/components/WebhookListTable/WebhookListTable.module.scss @@ -0,0 +1,38 @@ +/* + * 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. + */ + +.table { + --typography-size: 12px; + --typography-weight: 400; + --line-height: 20px; + padding: var(--spacing-large); + + [role='cell'], + [role='columnheader'] { + width: auto !important; + padding-right: var(--spacing-small); + } + + div[class*='TableV2--cells'], + div[class*='TableV2--header'] { + display: grid !important; + grid-template-columns: minmax(var(--har-table-name-column-min-width), 1fr) 1fr 50px 50px; + } +} + +.tableRow { + position: relative; +} diff --git a/web/src/ar/pages/webhook-list/components/WebhookListTable/WebhookListTable.module.scss.d.ts b/web/src/ar/pages/webhook-list/components/WebhookListTable/WebhookListTable.module.scss.d.ts new file mode 100644 index 000000000..03f6c3aff --- /dev/null +++ b/web/src/ar/pages/webhook-list/components/WebhookListTable/WebhookListTable.module.scss.d.ts @@ -0,0 +1,20 @@ +/* + * 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 table: string +export declare const tableRow: string diff --git a/web/src/ar/pages/webhook-list/components/WebhookListTable/WebhookListTable.tsx b/web/src/ar/pages/webhook-list/components/WebhookListTable/WebhookListTable.tsx new file mode 100644 index 000000000..49db3664d --- /dev/null +++ b/web/src/ar/pages/webhook-list/components/WebhookListTable/WebhookListTable.tsx @@ -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 from 'react' +import classNames from 'classnames' +import type { Column } from 'react-table' +import { useHistory } from 'react-router-dom' +import { type PaginationProps, TableV2 } from '@harnessio/uicore' +import type { ListWebhooks, Webhook } from '@harnessio/react-har-service-client' + +import { useStrings } from '@ar/frameworks/strings' +import { useParentHooks, useRoutes } from '@ar/hooks' +import { RepositoryDetailsTab } from '@ar/pages/repository-details/constants' + +import { + WebhookActionsCell, + WebhookListColumnActions, + WebhookNameCell, + WebhookStatusCell, + WebhookTriggerCell +} from './WebhookListTableCells' + +import css from './WebhookListTable.module.scss' + +interface WebhookListSortBy { + sort: 'name' +} + +export interface WebhookListTableProps extends WebhookListColumnActions { + data: ListWebhooks + gotoPage: (pageNumber: number) => void + onPageSizeChange?: PaginationProps['onPageSizeChange'] + setSortBy: (sortBy: string[]) => void + sortBy: string[] + minimal?: boolean +} + +export default function WebhookListTable(props: WebhookListTableProps): JSX.Element { + const { data, gotoPage, onPageSizeChange, readonly, sortBy, setSortBy } = props + const { useDefaultPaginationProps } = useParentHooks() + const { getString } = useStrings() + const history = useHistory() + const routes = useRoutes() + const [currentSort, currentOrder] = sortBy || [] + + const { webhooks, itemCount = 0, pageCount = 0, pageIndex, pageSize = 0 } = data + const paginationProps = useDefaultPaginationProps({ + itemCount, + pageSize, + pageCount, + pageIndex, + gotoPage, + onPageSizeChange + }) + + const columns: Column[] = React.useMemo(() => { + const getServerSortProps = (id: string) => { + return { + enableServerSort: true, + isServerSorted: currentSort === id, + isServerSortedDesc: currentOrder === 'DESC', + getSortedColumn: ({ sort }: WebhookListSortBy) => { + setSortBy([sort, currentOrder === 'DESC' ? 'ASC' : 'DESC']) + } + } + } + return [ + { + Header: getString('webhookList.table.columns.name'), + accessor: 'name', + Cell: WebhookNameCell, + serverSortProps: getServerSortProps('name'), + readonly: readonly + }, + { + Header: getString('webhookList.table.columns.trigger'), + accessor: 'triggers', + Cell: WebhookTriggerCell, + disableSortBy: true + }, + { + Header: '', + accessor: 'latestExecutionResult', + Cell: WebhookStatusCell, + disableSortBy: true + }, + { + Header: '', + accessor: 'menu', + Cell: WebhookActionsCell, + disableSortBy: true + } + ].filter(Boolean) as unknown as Column[] + }, [currentOrder, currentSort, getString, readonly]) + + return ( + css.tableRow} + onRowClick={rowDetails => { + // TODO: navigate to webhook details page + history.push( + routes.toARRepositoryDetailsTab({ + repositoryIdentifier: rowDetails.identifier, + tab: RepositoryDetailsTab.WEBHOOKS + }) + ) + }} + /> + ) +} diff --git a/web/src/ar/pages/webhook-list/components/WebhookListTable/WebhookListTableCells.tsx b/web/src/ar/pages/webhook-list/components/WebhookListTable/WebhookListTableCells.tsx new file mode 100644 index 000000000..6848666ed --- /dev/null +++ b/web/src/ar/pages/webhook-list/components/WebhookListTable/WebhookListTableCells.tsx @@ -0,0 +1,123 @@ +/* + * 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 { Icon, IconProps } from '@harnessio/icons' +import { Color, FontVariation } from '@harnessio/design-system' +import { Container, getErrorInfoFromErrorObject, Layout, Text, Toggle, useToaster } from '@harnessio/uicore' +import { updateWebhook, type Trigger, type Webhook } from '@harnessio/react-har-service-client' +import type { Cell, CellValue, ColumnInstance, Renderer, Row, TableInstance } from 'react-table' + +import { useGetSpaceRef } from '@ar/hooks' +import { killEvent } from '@ar/common/utils' +import { useStrings } from '@ar/frameworks/strings' +import ActionButton from '@ar/components/ActionButton/ActionButton' + +import { DefaultStatusIconMap, WebhookStatusIconMap, WebhookTriggerLabelMap } from '../../constants' + +type CellTypeWithActions, V = any> = TableInstance & { + column: ColumnInstance + row: Row + cell: Cell + value: CellValue +} + +type CellType = Renderer> + +export interface WebhookListColumnActions { + refetchList?: () => void + readonly?: boolean +} + +export const WebhookNameCell: Renderer<{ + row: Row + column: ColumnInstance & WebhookListColumnActions +}> = ({ row, column }) => { + const { name, enabled, identifier } = row.original + const { readonly } = column + const [isEnabled, setIsEnabled] = useState(enabled) + const registryRef = useGetSpaceRef() + + const { showError, clear } = useToaster() + + const handleUpdateToggle = async (checked: boolean) => { + setIsEnabled(checked) + try { + await updateWebhook({ + registry_ref: registryRef, + webhook_identifier: identifier, + body: { + ...row.original, + enabled: checked + } + }) + } catch (e) { + clear() + showError(getErrorInfoFromErrorObject(e as Error)) + setIsEnabled(enabled) + } + } + + return ( + + + + + + + {name} + + + ) +} + +export const WebhookTriggerCell: CellType = ({ value }) => { + const { getString } = useStrings() + const getDisplayText = () => { + if (!value || !value.length) return getString('all') + return value + .map((each: Trigger) => { + if (WebhookTriggerLabelMap[each]) return getString(WebhookTriggerLabelMap[each]) + return each + }) + .join(', ') + } + return ( + + {getDisplayText()} + + ) +} + +export const WebhookStatusCell: CellType = ({ row }) => { + const { original } = row + const { latestExecutionResult } = original + const iconProps: IconProps = + latestExecutionResult && WebhookStatusIconMap[latestExecutionResult] + ? WebhookStatusIconMap[latestExecutionResult] + : DefaultStatusIconMap + return +} + +export const WebhookActionsCell: CellType = () => { + const [open, setOpen] = useState(false) + return ( + + {/* TODO: Add webhook actions here */} + <>Option 1 + + ) +} diff --git a/web/src/ar/pages/webhook-list/constants.ts b/web/src/ar/pages/webhook-list/constants.ts new file mode 100644 index 000000000..1dde82552 --- /dev/null +++ b/web/src/ar/pages/webhook-list/constants.ts @@ -0,0 +1,35 @@ +/* + * 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 { Color } from '@harnessio/design-system' +import type { IconProps } from '@harnessio/icons' +import type { Trigger, WebhookExecResult } from '@harnessio/react-har-service-client' + +import type { StringKeys } from '@ar/frameworks/strings' + +export const WebhookTriggerLabelMap: Record = { + ARTIFACT_CREATION: 'webhookList.triggers.artifactCreation', + ARTIFACT_DELETION: 'webhookList.triggers.artifactDeletion', + ARTIFACT_MODIFICATION: 'webhookList.triggers.artifactModification' +} + +export const WebhookStatusIconMap: Record = { + SUCCESS: { name: 'dot', color: Color.SUCCESS }, + RETRIABLE_ERROR: { name: 'dot', color: Color.WARNING }, + FATAL_ERROR: { name: 'dot', color: Color.ERROR } +} + +export const DefaultStatusIconMap: IconProps = { name: 'dot', color: Color.GREY_500 } diff --git a/web/src/ar/pages/webhook-list/mockData.ts b/web/src/ar/pages/webhook-list/mockData.ts new file mode 100644 index 000000000..5e623db29 --- /dev/null +++ b/web/src/ar/pages/webhook-list/mockData.ts @@ -0,0 +1,50 @@ +/* + * 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 type { ListWebhooks } from '@harnessio/react-har-service-client' + +export const MOCK_WEBHOK_LIST_TABLE: ListWebhooks = { + itemCount: 10, + pageCount: 1, + pageIndex: 0, + pageSize: 10, + webhooks: [ + { + name: 'Webhook 1', + identifier: 'webhook-1', + triggers: ['ARTIFACT_CREATION'], + url: 'https://webhook-1.com', + insecure: false, + enabled: true + }, + { + name: 'Webhook 2', + identifier: 'webhook-2', + triggers: ['ARTIFACT_CREATION', 'ARTIFACT_DELETION'], + url: 'https://webhook-2.com', + insecure: false, + enabled: true + }, + { + name: 'Webhook 3', + identifier: 'webhook-3', + triggers: ['ARTIFACT_CREATION', 'ARTIFACT_DELETION', 'ARTIFACT_MODIFICATION'], + url: 'https://webhook-3.com', + insecure: false, + enabled: true + } + ] +} diff --git a/web/src/ar/pages/webhook-list/strings/strings.en.yaml b/web/src/ar/pages/webhook-list/strings/strings.en.yaml new file mode 100644 index 000000000..a5b28006d --- /dev/null +++ b/web/src/ar/pages/webhook-list/strings/strings.en.yaml @@ -0,0 +1,10 @@ +newWebhook: New Webhook +triggers: + artifactCreation: 'Artifact Creation' + artifactDeletion: 'Artifact Deletion' + artifactModification: 'Artifact Modification' +table: + columns: + name: Webhook + trigger: Event + noWebhooksTitle: There are no webhooks available diff --git a/web/src/ar/pages/webhook-list/utils.ts b/web/src/ar/pages/webhook-list/utils.ts new file mode 100644 index 000000000..34fc307c3 --- /dev/null +++ b/web/src/ar/pages/webhook-list/utils.ts @@ -0,0 +1,42 @@ +/* + * 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 { useMemo } from 'react' +import type { ListWebhooksQueryQueryParams } from '@harnessio/react-har-service-client' + +import { useParentHooks } from '@ar/hooks' +import { DEFAULT_PAGE_INDEX, DEFAULT_PAGE_SIZE } from '@ar/constants' +import type { UseQueryParamsOptions } from '@ar/__mocks__/hooks' + +export type WebhookListPageQueryParams = ListWebhooksQueryQueryParams & { + searchTerm?: string + sort: string[] +} + +export const useListWebhooksQueryParamOptions = (): UseQueryParamsOptions => { + const { useQueryParamsOptions } = useParentHooks() + const _options = useQueryParamsOptions( + { + page: DEFAULT_PAGE_INDEX, + size: DEFAULT_PAGE_SIZE, + sort: [] + }, + { ignoreEmptyString: false } + ) + const options = useMemo(() => ({ ..._options, strictNullHandling: true }), [_options]) + + return options +} diff --git a/web/src/ar/strings/strings.en.yaml b/web/src/ar/strings/strings.en.yaml index 568c66ca4..b86adc90f 100644 --- a/web/src/ar/strings/strings.en.yaml +++ b/web/src/ar/strings/strings.en.yaml @@ -26,6 +26,7 @@ na: N/A cancel: Cancel comingSoon: Coming Soon. failedToLoadData: Failed to load data. Please try again! +all: All noResultsFound: No results found optionalField: '{{name}} (optional)' description: '{{ $.versionDetails.overview.generalInformation.description }}' diff --git a/web/src/ar/strings/types.ts b/web/src/ar/strings/types.ts index 3b5789acd..d58d4f1b3 100644 --- a/web/src/ar/strings/types.ts +++ b/web/src/ar/strings/types.ts @@ -228,6 +228,13 @@ export interface StringsMap { 'versionList.table.columns.size': string 'versionList.table.columns.version': string 'versionList.table.noVersionsTitle': string + 'webhookList.newWebhook': string + 'webhookList.table.columns.name': string + 'webhookList.table.columns.trigger': string + 'webhookList.table.noWebhooksTitle': string + 'webhookList.triggers.artifactCreation': string + 'webhookList.triggers.artifactDeletion': string + 'webhookList.triggers.artifactModification': string 'actions.delete': string 'actions.edit': string 'actions.quarantine': string @@ -235,6 +242,7 @@ export interface StringsMap { 'actions.scan': string 'actions.setupClient': string add: string + all: string 'badges.artifactRegistry': string 'badges.upstreamProxy': string 'breadcrumbs.artifacts': string diff --git a/web/yarn.lock b/web/yarn.lock index 0b6b5bb66..85a0bc8c2 100644 --- a/web/yarn.lock +++ b/web/yarn.lock @@ -1945,10 +1945,10 @@ yargs "^17.6.2" zod "^3.19.1" -"@harnessio/react-har-service-client@^0.4.0": - version "0.4.0" - resolved "https://registry.yarnpkg.com/@harnessio/react-har-service-client/-/react-har-service-client-0.4.0.tgz#ad0deb70502f8ff51c7199d72dd67aa7a13640b4" - integrity sha512-ndVz0Ig0FHHwgDy1oZVQ7I2epFgM0dnYLLAUHOLMzaqvcV6pN8RCuawtygcFi9K2DKMfFQieWTuI9UjVoB8M+w== +"@harnessio/react-har-service-client@^0.6.0": + version "0.6.0" + resolved "https://registry.yarnpkg.com/@harnessio/react-har-service-client/-/react-har-service-client-0.6.0.tgz#25253fd935fe6a28a5d26d98148ba0ba51d545ef" + integrity sha512-jCCCInwmVoCWrambIop6dK8SvJXHpsq+8MdZNPbguMPjJgqR0d6i6Ms+4lpfBswJ/5TVVEvo/uFJhlAUVtf2fQ== dependencies: "@harnessio/oats-cli" "^3.0.0"