diff --git a/openmetadata-ui/src/main/resources/ui/playwright/support/entity/MlModelClass.ts b/openmetadata-ui/src/main/resources/ui/playwright/support/entity/MlModelClass.ts index e21c6d6e703..4ccad160d37 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/support/entity/MlModelClass.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/support/entity/MlModelClass.ts @@ -17,6 +17,14 @@ import { visitEntityPage } from '../../utils/entity'; import { EntityTypeEndpoint } from './Entity.interface'; import { EntityClass } from './EntityClass'; +type ResponseDataType = { + name: string; + displayName: string; + description: string; + id: string; + fullyQualifiedName: string; +}; + export class MlModelClass extends EntityClass { service = { name: `pw-ml-model-service-${uuid()}`, @@ -44,8 +52,8 @@ export class MlModelClass extends EntityClass { ], }; - serviceResponseData: unknown; - entityResponseData: unknown; + serviceResponseData: ResponseDataType; + entityResponseData: ResponseDataType; constructor(name?: string) { super(EntityTypeEndpoint.MlModel); @@ -81,9 +89,7 @@ export class MlModelClass extends EntityClass { patchData: Operation[]; }) { const response = await apiContext.patch( - `/api/v1/mlmodels/${ - (this.entityResponseData as { id: string })?.id ?? '' - }`, + `/api/v1/mlmodels/${this.entityResponseData.id}`, { data: patchData, headers: { diff --git a/openmetadata-ui/src/main/resources/ui/playwright/support/user/UserClass.ts b/openmetadata-ui/src/main/resources/ui/playwright/support/user/UserClass.ts index ad11e2ac573..0d1bb4ed06c 100644 --- a/openmetadata-ui/src/main/resources/ui/playwright/support/user/UserClass.ts +++ b/openmetadata-ui/src/main/resources/ui/playwright/support/user/UserClass.ts @@ -11,6 +11,7 @@ * limitations under the License. */ import { APIRequestContext, Page } from '@playwright/test'; +import { Operation } from 'fast-json-patch'; import { generateRandomUsername } from '../../utils/user'; type ResponseDataType = { @@ -36,6 +37,30 @@ export class UserClass { return response.body; } + async patch({ + apiContext, + patchData, + }: { + apiContext: APIRequestContext; + patchData: Operation[]; + }) { + const response = await apiContext.patch( + `/api/v1/users/${this.responseData.id}`, + { + data: patchData, + headers: { + 'Content-Type': 'application/json-patch+json', + }, + } + ); + + this.responseData = await response.json(); + + return { + entity: response.body, + }; + } + async delete(apiContext: APIRequestContext) { const response = await apiContext.delete( `/api/v1/users/${this.responseData.id}?recursive=false&hardDelete=true` diff --git a/openmetadata-ui/src/main/resources/ui/src/assets/svg/location.svg b/openmetadata-ui/src/main/resources/ui/src/assets/svg/location.svg new file mode 100644 index 00000000000..07fd59f8f77 --- /dev/null +++ b/openmetadata-ui/src/main/resources/ui/src/assets/svg/location.svg @@ -0,0 +1,4 @@ + + + + diff --git a/openmetadata-ui/src/main/resources/ui/src/assets/svg/metadata-service.svg b/openmetadata-ui/src/main/resources/ui/src/assets/svg/metadata-service.svg new file mode 100644 index 00000000000..6b4679d8de1 --- /dev/null +++ b/openmetadata-ui/src/main/resources/ui/src/assets/svg/metadata-service.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/FeedEditor/FeedEditor.tsx b/openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/FeedEditor/FeedEditor.tsx index 359cfa5700c..711b92d37b4 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/FeedEditor/FeedEditor.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/ActivityFeed/FeedEditor/FeedEditor.tsx @@ -140,16 +140,16 @@ export const FeedEditor = forwardRef( ` : ''; - const icon = ReactDOMServer.renderToString( - getEntityIcon(item.type as string) - ); + const icon = getEntityIcon(item.type as string); + + const iconString = ReactDOMServer.renderToString(icon ?? <>); const typeSpan = !breadcrumbEle ? `${item.type}` : ''; const result = `
-
${icon}
+
${iconString}
${breadcrumbEle}
diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Explore/ExploreTree/ExploreTree.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Explore/ExploreTree/ExploreTree.tsx index 37f87666881..044969a93a4 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Explore/ExploreTree/ExploreTree.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Explore/ExploreTree/ExploreTree.tsx @@ -136,7 +136,7 @@ const ExploreTree = ({ onFieldValueSelect }: ExploreTreeProps) => { let logo = undefined; if (isEntityType) { - logo = getEntityIcon(bucket.key, 'service-icon w-4 h-4'); + logo = getEntityIcon(bucket.key, 'service-icon w-4 h-4') ?? <>; } else if (isServiceType) { const serviceIcon = serviceUtilClassBase.getServiceLogo(bucket.key); logo = ( diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/de-de.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/de-de.json index c1013f493b0..e7a9fa22849 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/de-de.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/de-de.json @@ -744,6 +744,7 @@ "no-description": "Keine Beschreibung", "no-diff-available": "Keine Unterschiede verfügbar", "no-entity": "Keine {{entity}}", + "no-entity-selected": "No {{entity}} Selected", "no-matching-data-asset": "Keine passenden Datenanlagen gefunden", "no-of-test": " Nr. der Tests", "no-owner": "No Owner", diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/en-us.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/en-us.json index 75431b7a8fd..7262a8cee77 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/en-us.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/en-us.json @@ -744,6 +744,7 @@ "no-description": "No description", "no-diff-available": "No diff available", "no-entity": "No {{entity}}", + "no-entity-selected": "No {{entity}} Selected", "no-matching-data-asset": "No matching data assets found", "no-of-test": " No. of Test", "no-owner": "No Owner", diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/es-es.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/es-es.json index 4757e7d1d7b..f3ad058e416 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/es-es.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/es-es.json @@ -744,6 +744,7 @@ "no-description": "Sin descripción", "no-diff-available": "Sin diferencia disponible", "no-entity": "No hay {{entity}}", + "no-entity-selected": "No {{entity}} Selected", "no-matching-data-asset": "No se encontraron activos de datos coincidentes", "no-of-test": "No. de prueba", "no-owner": "No Owner", diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/fr-fr.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/fr-fr.json index 8818ce7115f..197a374a291 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/fr-fr.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/fr-fr.json @@ -744,6 +744,7 @@ "no-description": "Aucune description", "no-diff-available": "Aucune différence disponible", "no-entity": "Pas de {{entity}}", + "no-entity-selected": "No {{entity}} Selected", "no-matching-data-asset": "Aucun actif de données trouvé", "no-of-test": " No. de Tests", "no-owner": "Aucun propriétaire", diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/he-he.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/he-he.json index fc112f56850..d2d7379f34b 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/he-he.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/he-he.json @@ -744,6 +744,7 @@ "no-description": "-", "no-diff-available": "אין הבדל זמין", "no-entity": "אין {{entity}}", + "no-entity-selected": "No {{entity}} Selected", "no-matching-data-asset": "לא נמצאו נכסי נתונים תואמים", "no-of-test": "מספר הבדיקות", "no-owner": "No Owner", diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/ja-jp.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/ja-jp.json index a1f4b099c8c..851403ddb52 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/ja-jp.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/ja-jp.json @@ -744,6 +744,7 @@ "no-description": "説明がありません", "no-diff-available": "差分を見ることはできません", "no-entity": "No {{entity}}", + "no-entity-selected": "No {{entity}} Selected", "no-matching-data-asset": "マッチするデータアセットはありません", "no-of-test": " テスト番号", "no-owner": "No Owner", diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/nl-nl.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/nl-nl.json index d3074701f3f..f8c49766b4f 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/nl-nl.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/nl-nl.json @@ -744,6 +744,7 @@ "no-description": "Geen beschrijving", "no-diff-available": "Geen verschil beschikbaar", "no-entity": "Geen {{entity}}", + "no-entity-selected": "No {{entity}} Selected", "no-matching-data-asset": "Geen overeenkomende data-assets gevonden", "no-of-test": " Aantal tests", "no-owner": "No Owner", diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/pt-br.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/pt-br.json index 9f7e09a13b3..50a7bfaf592 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/pt-br.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/pt-br.json @@ -744,6 +744,7 @@ "no-description": "Sem descrição", "no-diff-available": "Nenhuma diferença disponível", "no-entity": "Nenhum(a) {{entity}}", + "no-entity-selected": "No {{entity}} Selected", "no-matching-data-asset": "Nenhum ativo de dados correspondente encontrado", "no-of-test": " Nº de Teste", "no-owner": "No Owner", diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/ru-ru.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/ru-ru.json index 8d9e7a32da1..133fe29483b 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/ru-ru.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/ru-ru.json @@ -744,6 +744,7 @@ "no-description": "Нет описания", "no-diff-available": "Нет различий", "no-entity": "{{entity}} отсутствует", + "no-entity-selected": "No {{entity}} Selected", "no-matching-data-asset": "Подходящие объекты данных не найдены", "no-of-test": "№ теста", "no-owner": "No Owner", diff --git a/openmetadata-ui/src/main/resources/ui/src/locale/languages/zh-cn.json b/openmetadata-ui/src/main/resources/ui/src/locale/languages/zh-cn.json index 46870241d3f..4073dac0221 100644 --- a/openmetadata-ui/src/main/resources/ui/src/locale/languages/zh-cn.json +++ b/openmetadata-ui/src/main/resources/ui/src/locale/languages/zh-cn.json @@ -744,6 +744,7 @@ "no-description": "无描述", "no-diff-available": "没有可用的差异", "no-entity": "没有{{entity}}", + "no-entity-selected": "No {{entity}} Selected", "no-matching-data-asset": "未找到匹配的数据资产", "no-of-test": "测试数量", "no-owner": "No Owner", diff --git a/openmetadata-ui/src/main/resources/ui/src/rest/miscAPI.ts b/openmetadata-ui/src/main/resources/ui/src/rest/miscAPI.ts index 433e3a2a68d..6b39a5c58c5 100644 --- a/openmetadata-ui/src/main/resources/ui/src/rest/miscAPI.ts +++ b/openmetadata-ui/src/main/resources/ui/src/rest/miscAPI.ts @@ -26,6 +26,7 @@ import { SearchResponse, } from '../interface/search.interface'; import { getSearchAPIQueryParams } from '../utils/SearchUtils'; +import { escapeESReservedCharacters } from '../utils/StringsUtils'; import APIClient from './index'; export const searchData = ( @@ -264,7 +265,9 @@ export const getAggregateFieldOptions = ( value: string, q: string ) => { - const withWildCardValue = value ? `.*${value}.*` : '.*'; + const withWildCardValue = value + ? `.*${escapeESReservedCharacters(value)}.*` + : '.*'; const params = { index, field, diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/Alerts/AlertsUtil.tsx b/openmetadata-ui/src/main/resources/ui/src/utils/Alerts/AlertsUtil.tsx index 88fcce7d96c..949ec7b9882 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/Alerts/AlertsUtil.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/utils/Alerts/AlertsUtil.tsx @@ -879,17 +879,21 @@ export const getSourceOptionsFromResourceList = ( showCheckbox?: boolean, selectedResource?: string[] ) => - resources.map((resource) => ({ - label: ( -
- {showCheckbox && ( - - )} -
{getEntityIcon(resource ?? '')}
- {getEntityNameLabel(resource ?? '')} -
- ), - value: resource ?? '', - })); + resources.map((resource) => { + const sourceIcon = getEntityIcon(resource ?? ''); + + return { + label: ( +
+ {showCheckbox && ( + + )} + {sourceIcon &&
{sourceIcon}
} + {getEntityNameLabel(resource ?? '')} +
+ ), + value: resource ?? '', + }; + }); diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/TableUtils.test.tsx b/openmetadata-ui/src/main/resources/ui/src/utils/TableUtils.test.tsx index 2a3c7767794..2dbe0fc6964 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/TableUtils.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/utils/TableUtils.test.tsx @@ -11,7 +11,11 @@ * limitations under the License. */ import { TagLabel } from '../generated/entity/data/container'; -import { getTagsWithoutTier, getTierTags } from '../utils/TableUtils'; +import { + getEntityIcon, + getTagsWithoutTier, + getTierTags, +} from '../utils/TableUtils'; describe('TableUtils', () => { it('getTierTags should return the correct usage percentile', () => { @@ -39,5 +43,9 @@ describe('TableUtils', () => { ]); }); - // Add more tests for other functions in TableUtils... + it('getEntityIcon should return null if no icon is found', () => { + const result = getEntityIcon('entity'); + + expect(result).toBeNull(); + }); }); diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/TableUtils.tsx b/openmetadata-ui/src/main/resources/ui/src/utils/TableUtils.tsx index 5399d4243f8..acbfdf14571 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/TableUtils.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/utils/TableUtils.tsx @@ -65,6 +65,8 @@ import { ReactComponent as IconNotNull } from '../assets/svg/icon-not-null.svg'; import { ReactComponent as RoleIcon } from '../assets/svg/icon-role-grey.svg'; import { ReactComponent as IconUniqueLineThrough } from '../assets/svg/icon-unique-line-through.svg'; import { ReactComponent as IconUnique } from '../assets/svg/icon-unique.svg'; +import { ReactComponent as LocationIcon } from '../assets/svg/location.svg'; +import { ReactComponent as MetadataServiceIcon } from '../assets/svg/metadata-service.svg'; import { ReactComponent as NotificationIcon } from '../assets/svg/notification.svg'; import { ReactComponent as PolicyIcon } from '../assets/svg/policies.svg'; import { ReactComponent as ServicesIcon } from '../assets/svg/services.svg'; @@ -202,6 +204,7 @@ export const getEntityIcon = ( const entityIconMapping: Record = { [SearchIndex.DATABASE]: DatabaseIcon, [EntityType.DATABASE]: DatabaseIcon, + [SearchIndex.DATABASE_SERVICE]: DatabaseIcon, [EntityType.DATABASE_SERVICE]: DatabaseIcon, [SearchIndex.DATABASE_SCHEMA]: SchemaIcon, [EntityType.DATABASE_SCHEMA]: SchemaIcon, @@ -242,6 +245,7 @@ export const getEntityIcon = ( [EntityType.CHART]: ChartIcon, [SearchIndex.TABLE]: TableIcon, [EntityType.TABLE]: TableIcon, + [EntityType.METADATA_SERVICE]: MetadataServiceIcon, [SearchIndex.DATA_PRODUCT]: DataProductIcon, [EntityType.DATA_PRODUCT]: DataProductIcon, [EntityType.TEST_CASE]: IconTestSuite, @@ -266,6 +270,7 @@ export const getEntityIcon = ( ['services']: ServicesIcon, ['automator']: AutomatorBotIcon, ['notification']: NotificationIcon, + ['location']: LocationIcon, }; switch (indexType) { @@ -284,7 +289,8 @@ export const getEntityIcon = ( break; } - return Icon ? : <>; + // If icon is not found, return null + return Icon ? : null; }; export const getServiceIcon = (source: SourceType) => {