mirror of
				https://github.com/open-metadata/OpenMetadata.git
				synced 2025-10-31 02:29:03 +00:00 
			
		
		
		
	* Fix #18332: Do not consolidate changes for Parent Entities * Fix #18332: Do not consolidate changes for Parent Entities * added no data placeholder when no tags there * fix failing playwright test due to consolidation changes and added the missing services * Fix tests * Fix parent entity change notifications * Fix tests * Fix parent entity change notifications * Fix tests * Fix tests --------- Co-authored-by: Ashish Gupta <ashish@getcollate.io>
This commit is contained in:
		
							parent
							
								
									2539ffa8de
								
							
						
					
					
						commit
						680ace99b3
					
				| @ -243,6 +243,7 @@ public final class Entity { | ||||
|   public static final String DOCUMENT = "document"; | ||||
|   // ServiceType - Service Entity name map | ||||
|   static final Map<ServiceType, String> SERVICE_TYPE_ENTITY_MAP = new EnumMap<>(ServiceType.class); | ||||
|   public static final List<String> PARENT_ENTITY_TYPES = new ArrayList<>(); | ||||
| 
 | ||||
|   static { | ||||
|     SERVICE_TYPE_ENTITY_MAP.put(ServiceType.DATABASE, DATABASE_SERVICE); | ||||
| @ -254,6 +255,25 @@ public final class Entity { | ||||
|     SERVICE_TYPE_ENTITY_MAP.put(ServiceType.STORAGE, STORAGE_SERVICE); | ||||
|     SERVICE_TYPE_ENTITY_MAP.put(ServiceType.SEARCH, SEARCH_SERVICE); | ||||
|     SERVICE_TYPE_ENTITY_MAP.put(ServiceType.API, API_SERVICE); | ||||
|     PARENT_ENTITY_TYPES.addAll( | ||||
|         listOf( | ||||
|             DATABASE_SERVICE, | ||||
|             DASHBOARD_SERVICE, | ||||
|             MESSAGING_SERVICE, | ||||
|             MLMODEL_SERVICE, | ||||
|             PIPELINE_SERVICE, | ||||
|             API_SERVICE, | ||||
|             API_COLLCECTION, | ||||
|             STORAGE_SERVICE, | ||||
|             METADATA_SERVICE, | ||||
|             SEARCH_SERVICE, | ||||
|             DATABASE, | ||||
|             DATABASE_SCHEMA, | ||||
|             CLASSIFICATION, | ||||
|             GLOSSARY, | ||||
|             DOMAIN, | ||||
|             TEST_SUITE, | ||||
|             TEAM)); | ||||
|   } | ||||
| 
 | ||||
|   private Entity() {} | ||||
|  | ||||
| @ -39,6 +39,7 @@ public class APICollectionRepository extends EntityRepository<APICollection> { | ||||
|         "", | ||||
|         ""); | ||||
|     supportsSearch = true; | ||||
|     parent = true; | ||||
|   } | ||||
| 
 | ||||
|   @Override | ||||
|  | ||||
| @ -16,5 +16,6 @@ public class APIServiceRepository extends ServiceEntityRepository<ApiService, Ap | ||||
|         "", | ||||
|         ServiceType.API); | ||||
|     supportsSearch = true; | ||||
|     parent = true; | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -54,6 +54,7 @@ public class ClassificationRepository extends EntityRepository<Classification> { | ||||
|     quoteFqn = true; | ||||
|     supportsSearch = true; | ||||
|     renameAllowed = true; | ||||
|     parent = true; | ||||
|   } | ||||
| 
 | ||||
|   @Override | ||||
|  | ||||
| @ -33,5 +33,6 @@ public class DashboardServiceRepository | ||||
|         "", | ||||
|         ServiceType.DASHBOARD); | ||||
|     supportsSearch = true; | ||||
|     parent = true; | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -69,6 +69,7 @@ public class DatabaseRepository extends EntityRepository<Database> { | ||||
|         "", | ||||
|         ""); | ||||
|     supportsSearch = true; | ||||
|     parent = true; | ||||
|     fieldFetchers.put("name", this::fetchAndSetService); | ||||
|   } | ||||
| 
 | ||||
|  | ||||
| @ -74,6 +74,7 @@ public class DatabaseSchemaRepository extends EntityRepository<DatabaseSchema> { | ||||
|         "", | ||||
|         ""); | ||||
|     supportsSearch = true; | ||||
|     parent = true; | ||||
|   } | ||||
| 
 | ||||
|   @Override | ||||
|  | ||||
| @ -60,6 +60,7 @@ public class DatabaseServiceRepository | ||||
|         "", | ||||
|         ServiceType.DATABASE); | ||||
|     supportsSearch = true; | ||||
|     parent = true; | ||||
|   } | ||||
| 
 | ||||
|   @Override | ||||
|  | ||||
| @ -46,6 +46,7 @@ public class DomainRepository extends EntityRepository<Domain> { | ||||
|         UPDATE_FIELDS, | ||||
|         UPDATE_FIELDS); | ||||
|     supportsSearch = true; | ||||
|     parent = true; | ||||
|   } | ||||
| 
 | ||||
|   @Override | ||||
|  | ||||
| @ -260,6 +260,7 @@ public abstract class EntityRepository<T extends EntityInterface> { | ||||
|   @Getter protected final Fields putFields; | ||||
| 
 | ||||
|   protected boolean supportsSearch = false; | ||||
|   @Getter protected boolean parent = false; | ||||
|   protected final Map<String, BiConsumer<List<T>, Fields>> fieldFetchers = new HashMap<>(); | ||||
| 
 | ||||
|   protected EntityRepository( | ||||
| @ -3276,7 +3277,9 @@ public abstract class EntityRepository<T extends EntityInterface> { | ||||
| 
 | ||||
|     private boolean consolidateChanges(T original, T updated, Operation operation) { | ||||
|       // If user is the same and the new update is with in the user session timeout | ||||
|       return original.getVersion() > 0.1 // First update on an entity that | ||||
|       return !parent // Parent entity shouldn't consolidate changes, as we need ChangeDescription to | ||||
|           // propagate to children | ||||
|           && original.getVersion() > 0.1 // First update on an entity that | ||||
|           && operation == Operation.PATCH | ||||
|           && !Boolean.TRUE.equals(original.getDeleted()) // Entity is not soft deleted | ||||
|           && !operation.isDelete() // Operation must be an update | ||||
| @ -3285,6 +3288,7 @@ public abstract class EntityRepository<T extends EntityInterface> { | ||||
|               .equals(updated.getUpdatedBy()) // Must be updated by the same user | ||||
|           && updated.getUpdatedAt() - original.getUpdatedAt() | ||||
|               <= sessionTimeoutMillis; // With in session timeout | ||||
|       // changes to children | ||||
|     } | ||||
| 
 | ||||
|     private T getPreviousVersion(T original) { | ||||
|  | ||||
| @ -89,6 +89,7 @@ public class GlossaryRepository extends EntityRepository<Glossary> { | ||||
|     quoteFqn = true; | ||||
|     supportsSearch = true; | ||||
|     renameAllowed = true; | ||||
|     parent = true; | ||||
|   } | ||||
| 
 | ||||
|   @Override | ||||
|  | ||||
| @ -34,5 +34,6 @@ public class MessagingServiceRepository | ||||
|         UPDATE_FIELDS, | ||||
|         ServiceType.MESSAGING); | ||||
|     supportsSearch = true; | ||||
|     parent = true; | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -19,5 +19,6 @@ public class MetadataServiceRepository | ||||
|         UPDATE_FIELDS, | ||||
|         ServiceType.METADATA); | ||||
|     supportsSearch = true; | ||||
|     parent = true; | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -34,5 +34,6 @@ public class MlModelServiceRepository | ||||
|         UPDATE_FIELDS, | ||||
|         ServiceType.ML_MODEL); | ||||
|     supportsSearch = true; | ||||
|     parent = true; | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -33,5 +33,6 @@ public class PipelineServiceRepository | ||||
|         "", | ||||
|         ServiceType.PIPELINE); | ||||
|     supportsSearch = true; | ||||
|     parent = true; | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -17,5 +17,6 @@ public class SearchServiceRepository | ||||
|         "", | ||||
|         ServiceType.SEARCH); | ||||
|     supportsSearch = true; | ||||
|     parent = true; | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -17,5 +17,6 @@ public class StorageServiceRepository | ||||
|         "", | ||||
|         ServiceType.STORAGE); | ||||
|     supportsSearch = true; | ||||
|     parent = true; | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -102,6 +102,7 @@ public class TeamRepository extends EntityRepository<Team> { | ||||
|         TEAM_UPDATE_FIELDS); | ||||
|     this.quoteFqn = true; | ||||
|     supportsSearch = true; | ||||
|     parent = true; | ||||
|   } | ||||
| 
 | ||||
|   @Override | ||||
|  | ||||
| @ -104,6 +104,7 @@ public class TestSuiteRepository extends EntityRepository<TestSuite> { | ||||
|         UPDATE_FIELDS); | ||||
|     quoteFqn = false; | ||||
|     supportsSearch = true; | ||||
|     parent = true; | ||||
|   } | ||||
| 
 | ||||
|   @Override | ||||
|  | ||||
| @ -449,7 +449,7 @@ public class SearchRepository { | ||||
|     Map<String, Object> fieldData = new HashMap<>(); | ||||
| 
 | ||||
|     if (changeDescription != null) { | ||||
|       for (FieldChange field : changeDescription.getFieldsAdded()) { | ||||
|       for (FieldChange field : changeDescription.getFieldsDeleted()) { | ||||
|         if (inheritableFields.contains(field.getName())) { | ||||
|           try { | ||||
|             if (field.getName().equals(FIELD_OWNERS)) { | ||||
| @ -458,24 +458,21 @@ public class SearchRepository { | ||||
|               for (EntityReference inheritedOwner : inheritedOwners) { | ||||
|                 inheritedOwner.setInherited(true); | ||||
|               } | ||||
|               fieldData.put("updatedOwners", inheritedOwners); | ||||
|               scriptTxt.append(ADD_OWNERS_SCRIPT); | ||||
|               fieldData.put("deletedOwners", inheritedOwners); | ||||
|               scriptTxt.append(REMOVE_OWNERS_SCRIPT); | ||||
|             } else { | ||||
|               EntityReference entityReference = | ||||
|                   JsonUtils.readValue(field.getNewValue().toString(), EntityReference.class); | ||||
|                   JsonUtils.readValue(field.getOldValue().toString(), EntityReference.class); | ||||
|               scriptTxt.append( | ||||
|                   String.format( | ||||
|                       PROPAGATE_ENTITY_REFERENCE_FIELD_SCRIPT, | ||||
|                       field.getName(), | ||||
|                       field.getName(), | ||||
|                       REMOVE_PROPAGATED_ENTITY_REFERENCE_FIELD_SCRIPT, | ||||
|                       field.getName(), | ||||
|                       field.getName(), | ||||
|                       field.getName())); | ||||
|               fieldData.put(field.getName(), entityReference); | ||||
|               fieldData.put(field.getName(), JsonUtils.getMap(entityReference)); | ||||
|             } | ||||
|           } catch (UnhandledServerException e) { | ||||
|             scriptTxt.append( | ||||
|                 String.format(PROPAGATE_FIELD_SCRIPT, field.getName(), field.getNewValue())); | ||||
|             scriptTxt.append(String.format(REMOVE_PROPAGATED_FIELD_SCRIPT, field.getName())); | ||||
|           } | ||||
|         } | ||||
|       } | ||||
| @ -507,7 +504,7 @@ public class SearchRepository { | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|       for (FieldChange field : changeDescription.getFieldsDeleted()) { | ||||
|       for (FieldChange field : changeDescription.getFieldsAdded()) { | ||||
|         if (inheritableFields.contains(field.getName())) { | ||||
|           try { | ||||
|             if (field.getName().equals(FIELD_OWNERS)) { | ||||
| @ -516,21 +513,24 @@ public class SearchRepository { | ||||
|               for (EntityReference inheritedOwner : inheritedOwners) { | ||||
|                 inheritedOwner.setInherited(true); | ||||
|               } | ||||
|               fieldData.put("deletedOwners", inheritedOwners); | ||||
|               scriptTxt.append(REMOVE_OWNERS_SCRIPT); | ||||
|               fieldData.put("updatedOwners", inheritedOwners); | ||||
|               scriptTxt.append(ADD_OWNERS_SCRIPT); | ||||
|             } else { | ||||
|               EntityReference entityReference = | ||||
|                   JsonUtils.readValue(field.getOldValue().toString(), EntityReference.class); | ||||
|                   JsonUtils.readValue(field.getNewValue().toString(), EntityReference.class); | ||||
|               scriptTxt.append( | ||||
|                   String.format( | ||||
|                       REMOVE_PROPAGATED_ENTITY_REFERENCE_FIELD_SCRIPT, | ||||
|                       PROPAGATE_ENTITY_REFERENCE_FIELD_SCRIPT, | ||||
|                       field.getName(), | ||||
|                       field.getName(), | ||||
|                       field.getName(), | ||||
|                       field.getName(), | ||||
|                       field.getName())); | ||||
|               fieldData.put(field.getName(), JsonUtils.getMap(entityReference)); | ||||
|               fieldData.put(field.getName(), entityReference); | ||||
|             } | ||||
|           } catch (UnhandledServerException e) { | ||||
|             scriptTxt.append(String.format(REMOVE_PROPAGATED_FIELD_SCRIPT, field.getName())); | ||||
|             scriptTxt.append( | ||||
|                 String.format(PROPAGATE_FIELD_SCRIPT, field.getName(), field.getNewValue())); | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|  | ||||
| @ -1549,13 +1549,24 @@ public abstract class EntityResourceTest<T extends EntityInterface, K extends Cr | ||||
|     checkOwnerOwns(TEAM11_REF, entity.getId(), true); | ||||
| 
 | ||||
|     // V0-2 (consolidated) - Change owner from TEAM_OWNER1 to USER_OWNER1 using PATCH request | ||||
|     if (!isParent()) { | ||||
|       json = JsonUtils.pojoToJson(entity); | ||||
|       entity.setOwners(List.of(USER1_REF)); | ||||
|     change = getChangeDescription(entity, CHANGE_CONSOLIDATED); | ||||
|       change = getChangeDescription(entity, getChangeType()); | ||||
|       fieldAdded(change, FIELD_OWNERS, List.of(USER1_REF)); | ||||
|     entity = patchEntityAndCheck(entity, json, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change); | ||||
|       entity = patchEntityAndCheck(entity, json, ADMIN_AUTH_HEADERS, getChangeType(), change); | ||||
|       checkOwnerOwns(USER1_REF, entity.getId(), true); | ||||
|       checkOwnerOwns(TEAM11_REF, entity.getId(), false); | ||||
|     } else { | ||||
|       json = JsonUtils.pojoToJson(entity); | ||||
|       entity.setOwners(List.of(USER1_REF)); | ||||
|       change = getChangeDescription(entity, getChangeType()); | ||||
|       fieldAdded(change, FIELD_OWNERS, List.of(USER1_REF)); | ||||
|       fieldDeleted(change, FIELD_OWNERS, List.of(TEAM11_REF)); | ||||
|       entity = patchEntityAndCheck(entity, json, ADMIN_AUTH_HEADERS, getChangeType(), change); | ||||
|       checkOwnerOwns(USER1_REF, entity.getId(), true); | ||||
|       checkOwnerOwns(TEAM11_REF, entity.getId(), false); | ||||
|     } | ||||
| 
 | ||||
|     // V0.2 (no change) - Set the owner to the existing owner. No ownership change must be recorded. | ||||
|     json = JsonUtils.pojoToJson(entity); | ||||
| @ -1565,11 +1576,20 @@ public abstract class EntityResourceTest<T extends EntityInterface, K extends Cr | ||||
| 
 | ||||
|     // V0.1 (revert) - Remove ownership (USER_OWNER1) using PATCH. We are back to original state no | ||||
|     // owner and no change | ||||
|     if (!isParent()) { | ||||
|       json = JsonUtils.pojoToJson(entity); | ||||
|       entity.setOwners(null); | ||||
|       change = getChangeDescription(entity, REVERT); | ||||
|       patchEntityAndCheck(entity, json, ADMIN_AUTH_HEADERS, REVERT, change); | ||||
|       checkOwnerOwns(USER1_REF, entity.getId(), false); | ||||
|     } else { | ||||
|       json = JsonUtils.pojoToJson(entity); | ||||
|       entity.setOwners(null); | ||||
|       change = getChangeDescription(entity, MINOR_UPDATE); | ||||
|       fieldDeleted(change, FIELD_OWNERS, List.of(USER1_REF)); | ||||
|       patchEntityAndCheck(entity, json, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change); | ||||
|       checkOwnerOwns(USER1_REF, entity.getId(), false); | ||||
|     } | ||||
| 
 | ||||
|     // set random type as entity. Check if the ownership validate. | ||||
|     T newEntity = entity; | ||||
| @ -1873,6 +1893,7 @@ public abstract class EntityResourceTest<T extends EntityInterface, K extends Cr | ||||
|     // | ||||
|     // Replace description, add tags tier, owner - Changes are consolidated | ||||
|     // | ||||
|     if (!isParent()) { | ||||
|       origJson = JsonUtils.pojoToJson(entity); | ||||
|       entity.setDescription("description1"); | ||||
|       entity.setDisplayName("displayName1"); | ||||
| @ -1891,9 +1912,7 @@ public abstract class EntityResourceTest<T extends EntityInterface, K extends Cr | ||||
|             FIELD_TAGS, | ||||
|             List.of(USER_ADDRESS_TAG_LABEL, GLOSSARY2_TERM1_LABEL, TIER1_TAG_LABEL)); | ||||
|       } | ||||
| 
 | ||||
|     entity = patchEntityAndCheck(entity, origJson, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change); | ||||
| 
 | ||||
|       entity = patchEntityAndCheck(entity, origJson, ADMIN_AUTH_HEADERS, getChangeType(), change); | ||||
|       // | ||||
|       // Remove description, tier, owner - Changes are reverted going to 0.1 version of the entity | ||||
|       // | ||||
| @ -1904,6 +1923,41 @@ public abstract class EntityResourceTest<T extends EntityInterface, K extends Cr | ||||
|       entity.setOwners(null); | ||||
|       entity.setTags(null); | ||||
|       patchEntityAndCheck(entity, origJson, ADMIN_AUTH_HEADERS, REVERT, change); | ||||
|     } else { | ||||
|       origJson = JsonUtils.pojoToJson(entity); | ||||
|       entity.setDescription("description1"); | ||||
|       entity.setDisplayName("displayName1"); | ||||
|       change = getChangeDescription(entity, MINOR_UPDATE); | ||||
|       fieldUpdated(change, "description", "description", "description1"); | ||||
|       fieldUpdated(change, "displayName", "displayName", "displayName1"); | ||||
|       if (supportsOwners) { | ||||
|         entity.setOwners(List.of(USER1_REF)); | ||||
|         fieldAdded(change, FIELD_OWNERS, List.of(USER1_REF)); | ||||
|         fieldDeleted(change, FIELD_OWNERS, List.of(TEAM11_REF)); | ||||
|       } | ||||
| 
 | ||||
|       if (supportsTags) { | ||||
|         entity.getTags().add(TIER1_TAG_LABEL); | ||||
|         fieldAdded(change, FIELD_TAGS, List.of(TIER1_TAG_LABEL)); | ||||
|       } | ||||
|       entity = patchEntityAndCheck(entity, origJson, ADMIN_AUTH_HEADERS, getChangeType(), change); | ||||
| 
 | ||||
|       origJson = JsonUtils.pojoToJson(entity); | ||||
|       change = getChangeDescription(entity, MINOR_UPDATE); | ||||
|       entity.setDescription(""); | ||||
|       entity.setDisplayName(null); | ||||
|       entity.setOwners(null); | ||||
|       entity.setTags(null); | ||||
|       fieldUpdated(change, "description", "description1", ""); | ||||
|       fieldDeleted(change, "displayName", "displayName1"); | ||||
|       if (supportsOwners) { | ||||
|         fieldDeleted(change, FIELD_OWNERS, List.of(USER1_REF)); | ||||
|       } | ||||
|       if (supportsTags) { | ||||
|         fieldDeleted(change, FIELD_TAGS, List.of(TIER1_TAG_LABEL)); | ||||
|       } | ||||
|       patchEntityAndCheck(entity, origJson, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   @Test | ||||
| @ -1942,11 +1996,12 @@ public abstract class EntityResourceTest<T extends EntityInterface, K extends Cr | ||||
| 
 | ||||
|     // Update description with a new description and the version changes as admin - the changes are | ||||
|     // consolidated | ||||
|     if (!isParent()) { | ||||
|       json = JsonUtils.pojoToJson(entity); | ||||
|       entity.setDescription("description2"); | ||||
|     change = getChangeDescription(entity, CHANGE_CONSOLIDATED); // New version remains the same | ||||
|       change = getChangeDescription(entity, getChangeType()); // Version changes | ||||
|       fieldUpdated(change, "description", "description", "description2"); | ||||
|     entity = patchEntityAndCheck(entity, json, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change); | ||||
|       entity = patchEntityAndCheck(entity, json, ADMIN_AUTH_HEADERS, getChangeType(), change); | ||||
| 
 | ||||
|       // Update displayName with a new displayName - but as USER1 | ||||
|       // Since the previous change is done by a different user, changes ** are not ** consolidated | ||||
| @ -1968,6 +2023,34 @@ public abstract class EntityResourceTest<T extends EntityInterface, K extends Cr | ||||
|       fieldUpdated(change, "displayName", "displayName", "displayName1"); | ||||
|       patchEntityAndCheck(entity, json, authHeaders(USER1.getName()), MINOR_UPDATE, change); | ||||
|       EntityUpdater.setSessionTimeout(10 * 60 * 10000); // Reset the session timeout back | ||||
| 
 | ||||
|     } else { | ||||
|       json = JsonUtils.pojoToJson(entity); | ||||
|       entity.setDescription("description2"); | ||||
|       change = getChangeDescription(entity, getChangeType()); // Version changes | ||||
|       fieldUpdated(change, "description", "description1", "description2"); | ||||
|       entity = patchEntityAndCheck(entity, json, ADMIN_AUTH_HEADERS, getChangeType(), change); | ||||
| 
 | ||||
|       // Update displayName with a new displayName - but as USER1 | ||||
|       // Since the previous change is done by a different user, changes ** are not ** consolidated | ||||
|       json = JsonUtils.pojoToJson(entity); | ||||
|       entity.setDisplayName("displayName"); | ||||
|       change = getChangeDescription(entity, MINOR_UPDATE); // Version changes | ||||
|       fieldAdded(change, "displayName", "displayName"); | ||||
|       entity = patchEntityAndCheck(entity, json, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change); | ||||
| 
 | ||||
|       // Update displayName to a new displayName. | ||||
|       // In this test, the user who previously made a change makes the change after session timeout. | ||||
|       // The changes are not consolidated. | ||||
|       EntityUpdater.setSessionTimeout(1); // Reduce the session timeout for this test | ||||
|       java.lang.Thread.sleep(2); | ||||
|       json = JsonUtils.pojoToJson(entity); | ||||
|       entity.setDisplayName("displayName1"); | ||||
|       change = getChangeDescription(entity, MINOR_UPDATE); // Version changes | ||||
|       fieldUpdated(change, "displayName", "displayName", "displayName1"); | ||||
|       patchEntityAndCheck(entity, json, authHeaders(USER1.getName()), MINOR_UPDATE, change); | ||||
|       EntityUpdater.setSessionTimeout(10 * 60 * 10000); // Reset the session timeout back | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   @Test | ||||
| @ -2058,17 +2141,21 @@ public abstract class EntityResourceTest<T extends EntityInterface, K extends Cr | ||||
|     JsonNode stringBValue = mapper.convertValue("stringB", JsonNode.class); | ||||
|     jsonNode.set("stringB", stringBValue); | ||||
|     entity.setExtension(jsonNode); | ||||
|     change = | ||||
|         getChangeDescription( | ||||
|             entity, CHANGE_CONSOLIDATED); // Patch operation update is consolidated in a session | ||||
|     change = getChangeDescription(entity, getChangeType()); // PATCH operation update is not | ||||
|     if (!isParent()) { | ||||
|       fieldUpdated( | ||||
|           change, | ||||
|           EntityUtil.getExtensionField("intA"), | ||||
|           mapper.convertValue(1, JsonNode.class), | ||||
|           intAValue); | ||||
|       fieldAdded(change, "extension", List.of(JsonUtils.getObjectNode("stringB", stringBValue))); | ||||
|     entity = patchEntityAndCheck(entity, json, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change); | ||||
|       entity = patchEntityAndCheck(entity, json, ADMIN_AUTH_HEADERS, getChangeType(), change); | ||||
|       assertEquals(JsonUtils.valueToTree(jsonNode), JsonUtils.valueToTree(entity.getExtension())); | ||||
|     } else { | ||||
|       fieldAdded(change, "extension", List.of(JsonUtils.getObjectNode("stringB", stringBValue))); | ||||
|       entity = patchEntityAndCheck(entity, json, ADMIN_AUTH_HEADERS, getChangeType(), change); | ||||
|       assertEquals(JsonUtils.valueToTree(jsonNode), JsonUtils.valueToTree(entity.getExtension())); | ||||
|     } | ||||
| 
 | ||||
|     // PUT and remove field intA from the entity extension - *** for BOT this should be ignored *** | ||||
|     JsonNode oldNode = JsonUtils.valueToTree(entity.getExtension()); | ||||
| @ -2088,6 +2175,7 @@ public abstract class EntityResourceTest<T extends EntityInterface, K extends Cr | ||||
|     assertEquals( | ||||
|         JsonUtils.valueToTree(create.getExtension()), JsonUtils.valueToTree(entity.getExtension())); | ||||
| 
 | ||||
|     if (!isParent()) { | ||||
|       // PATCH and remove field stringB from the entity extension | ||||
|       json = JsonUtils.pojoToJson(entity); | ||||
|       jsonNode.remove("stringB"); | ||||
| @ -2101,8 +2189,19 @@ public abstract class EntityResourceTest<T extends EntityInterface, K extends Cr | ||||
|           List.of( | ||||
|               JsonUtils.getObjectNode("intA", intAValue), | ||||
|               JsonUtils.getObjectNode("stringB", stringBValue))); | ||||
|     entity = patchEntityAndCheck(entity, json, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change); | ||||
|       entity = patchEntityAndCheck(entity, json, ADMIN_AUTH_HEADERS, getChangeType(), change); | ||||
|       assertEquals(JsonUtils.valueToTree(jsonNode), JsonUtils.valueToTree(entity.getExtension())); | ||||
|     } else { | ||||
|       json = JsonUtils.pojoToJson(entity); | ||||
|       jsonNode.remove("stringB"); | ||||
|       entity.setExtension(jsonNode); | ||||
|       change = | ||||
|           getChangeDescription( | ||||
|               entity, MINOR_UPDATE); // PATCH operation update is consolidated into a session | ||||
|       fieldDeleted(change, "extension", List.of(JsonUtils.getObjectNode("stringB", stringBValue))); | ||||
|       entity = patchEntityAndCheck(entity, json, ADMIN_AUTH_HEADERS, getChangeType(), change); | ||||
|       assertEquals(JsonUtils.valueToTree(jsonNode), JsonUtils.valueToTree(entity.getExtension())); | ||||
|     } | ||||
| 
 | ||||
|     // Now set the entity custom property to an invalid value | ||||
|     jsonNode.set( | ||||
| @ -4115,4 +4214,16 @@ public abstract class EntityResourceTest<T extends EntityInterface, K extends Cr | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   public UpdateType getChangeType() { | ||||
|     if (isParent()) { | ||||
|       return MINOR_UPDATE; | ||||
|     } else { | ||||
|       return CHANGE_CONSOLIDATED; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   public boolean isParent() { | ||||
|     return PARENT_ENTITY_TYPES.contains(entityType); | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -10,9 +10,7 @@ import static org.openmetadata.service.util.EntityUtil.fieldAdded; | ||||
| import static org.openmetadata.service.util.EntityUtil.fieldDeleted; | ||||
| import static org.openmetadata.service.util.EntityUtil.fieldUpdated; | ||||
| import static org.openmetadata.service.util.TestUtils.ADMIN_AUTH_HEADERS; | ||||
| import static org.openmetadata.service.util.TestUtils.UpdateType.CHANGE_CONSOLIDATED; | ||||
| import static org.openmetadata.service.util.TestUtils.UpdateType.MINOR_UPDATE; | ||||
| import static org.openmetadata.service.util.TestUtils.UpdateType.REVERT; | ||||
| import static org.openmetadata.service.util.TestUtils.assertEntityReferenceNames; | ||||
| import static org.openmetadata.service.util.TestUtils.assertListNotNull; | ||||
| import static org.openmetadata.service.util.TestUtils.assertListNull; | ||||
| @ -71,21 +69,17 @@ public class DomainResourceTest extends EntityResourceTest<Domain, CreateDomain> | ||||
|     fieldDeleted(change, "experts", listOf(USER2.getEntityReference())); | ||||
|     domain = updateAndCheckEntity(create, Status.OK, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change); | ||||
| 
 | ||||
|     // Add User2 back as expert using PATCH | ||||
|     // Version 0. 2 - Changes from this PATCH is consolidated with the previous change resulting in | ||||
|     // no change | ||||
|     String json = JsonUtils.pojoToJson(domain); | ||||
|     domain.withExperts(List.of(USER1.getEntityReference(), USER2.getEntityReference())); | ||||
|     change = getChangeDescription(domain, REVERT); | ||||
|     domain = patchEntityAndCheck(domain, json, ADMIN_AUTH_HEADERS, REVERT, change); | ||||
|     change = getChangeDescription(domain, MINOR_UPDATE); | ||||
|     fieldAdded(change, "experts", listOf(USER2.getEntityReference())); | ||||
|     domain = patchEntityAndCheck(domain, json, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change); | ||||
| 
 | ||||
|     // Remove User2 as expert using PATCH | ||||
|     // Version 0.1 - Changes from this PATCH is consolidated with the previous two changes resulting | ||||
|     // in deletion of USER2 | ||||
|     json = JsonUtils.pojoToJson(domain); | ||||
|     change = getChangeDescription(domain, REVERT); | ||||
|     change = getChangeDescription(domain, MINOR_UPDATE); | ||||
|     fieldDeleted(change, "experts", listOf(USER2.getEntityReference())); | ||||
|     domain.withExperts(List.of(USER1.getEntityReference())); | ||||
|     patchEntityAndCheck(domain, json, ADMIN_AUTH_HEADERS, REVERT, change); | ||||
|     patchEntityAndCheck(domain, json, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change); | ||||
|   } | ||||
| 
 | ||||
|   @Test | ||||
| @ -104,9 +98,9 @@ public class DomainResourceTest extends EntityResourceTest<Domain, CreateDomain> | ||||
|     // Changes from this PATCH is consolidated with the previous changes | ||||
|     String json = JsonUtils.pojoToJson(domain); | ||||
|     domain.withDomainType(DomainType.CONSUMER_ALIGNED); | ||||
|     change = getChangeDescription(domain, CHANGE_CONSOLIDATED); | ||||
|     fieldUpdated(change, "domainType", DomainType.AGGREGATE, DomainType.CONSUMER_ALIGNED); | ||||
|     patchEntityAndCheck(domain, json, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change); | ||||
|     change = getChangeDescription(domain, MINOR_UPDATE); | ||||
|     fieldUpdated(change, "domainType", DomainType.SOURCE_ALIGNED, DomainType.CONSUMER_ALIGNED); | ||||
|     patchEntityAndCheck(domain, json, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change); | ||||
|   } | ||||
| 
 | ||||
|   @Test | ||||
|  | ||||
| @ -37,11 +37,11 @@ import static org.openmetadata.schema.type.ProviderType.SYSTEM; | ||||
| import static org.openmetadata.schema.type.TaskType.RequestDescription; | ||||
| import static org.openmetadata.service.security.SecurityUtil.authHeaders; | ||||
| import static org.openmetadata.service.util.EntityUtil.fieldAdded; | ||||
| import static org.openmetadata.service.util.EntityUtil.fieldDeleted; | ||||
| import static org.openmetadata.service.util.EntityUtil.fieldUpdated; | ||||
| import static org.openmetadata.service.util.EntityUtil.getFqn; | ||||
| import static org.openmetadata.service.util.EntityUtil.toTagLabels; | ||||
| import static org.openmetadata.service.util.TestUtils.ADMIN_AUTH_HEADERS; | ||||
| import static org.openmetadata.service.util.TestUtils.UpdateType.CHANGE_CONSOLIDATED; | ||||
| import static org.openmetadata.service.util.TestUtils.UpdateType.MINOR_UPDATE; | ||||
| import static org.openmetadata.service.util.TestUtils.assertListNull; | ||||
| import static org.openmetadata.service.util.TestUtils.assertResponse; | ||||
| @ -168,11 +168,9 @@ public class GlossaryResourceTest extends EntityResourceTest<Glossary, CreateGlo | ||||
|     glossary.withReviewers(List.of(USER1_REF, USER2_REF)); | ||||
|     change = | ||||
|         getChangeDescription( | ||||
|             glossary, | ||||
|             CHANGE_CONSOLIDATED); // PATCH operation update is consolidated in a user session | ||||
|     fieldAdded(change, "reviewers", List.of(USER1_REF, USER2_REF)); | ||||
|     glossary = | ||||
|         patchEntityAndCheck(glossary, origJson, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change); | ||||
|             glossary, MINOR_UPDATE); // PATCH operation update is consolidated in a user session | ||||
|     fieldAdded(change, "reviewers", List.of(USER2_REF)); | ||||
|     glossary = patchEntityAndCheck(glossary, origJson, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change); | ||||
| 
 | ||||
|     // Create a glossary term and assign USER2 as a reviewer | ||||
|     GlossaryTermResourceTest glossaryTermResourceTest = new GlossaryTermResourceTest(); | ||||
| @ -220,10 +218,9 @@ public class GlossaryResourceTest extends EntityResourceTest<Glossary, CreateGlo | ||||
|     glossary.withReviewers(List.of(USER2_REF)); | ||||
|     change = | ||||
|         getChangeDescription( | ||||
|             glossary, | ||||
|             CHANGE_CONSOLIDATED); // PATCH operation update is consolidated in a user session | ||||
|     fieldAdded(change, "reviewers", List.of(USER2_REF)); | ||||
|     patchEntityAndCheck(glossary, origJson, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change); | ||||
|             glossary, MINOR_UPDATE); // PATCH operation update is consolidated in a user session | ||||
|     fieldDeleted(change, "reviewers", List.of(USER1_REF)); | ||||
|     patchEntityAndCheck(glossary, origJson, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change); | ||||
| 
 | ||||
|     // Verify that USER1_REF is removed from the reviewers for the terms inside the glossary | ||||
|     GLOSSARY_TERM1 = | ||||
|  | ||||
| @ -52,10 +52,8 @@ import static org.openmetadata.service.util.TestUtils.ADMIN_AUTH_HEADERS; | ||||
| import static org.openmetadata.service.util.TestUtils.TEST_AUTH_HEADERS; | ||||
| import static org.openmetadata.service.util.TestUtils.TEST_USER_NAME; | ||||
| import static org.openmetadata.service.util.TestUtils.USER_WITH_CREATE_HEADERS; | ||||
| import static org.openmetadata.service.util.TestUtils.UpdateType.CHANGE_CONSOLIDATED; | ||||
| import static org.openmetadata.service.util.TestUtils.UpdateType.MINOR_UPDATE; | ||||
| import static org.openmetadata.service.util.TestUtils.UpdateType.NO_CHANGE; | ||||
| import static org.openmetadata.service.util.TestUtils.UpdateType.REVERT; | ||||
| import static org.openmetadata.service.util.TestUtils.assertListNotNull; | ||||
| import static org.openmetadata.service.util.TestUtils.assertResponse; | ||||
| import static org.openmetadata.service.util.TestUtils.validateEntityReferences; | ||||
| @ -600,11 +598,12 @@ public class TeamResourceTest extends EntityResourceTest<Team, CreateTeam> { | ||||
|     bu2 = updateAndCheckEntity(create, OK, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change); | ||||
| 
 | ||||
|     // Change bu2 parent from Organization to bu1 using PATCH operation. | ||||
|     // Change from this PATCH is combined with the previous PUT resulting in no change | ||||
|     String json = JsonUtils.pojoToJson(bu2); | ||||
|     change = getChangeDescription(bu2, REVERT); | ||||
|     change = getChangeDescription(bu2, MINOR_UPDATE); | ||||
|     bu2.setParents(List.of(bu1.getEntityReference())); | ||||
|     patchEntityAndCheck(bu2, json, ADMIN_AUTH_HEADERS, REVERT, change); | ||||
|     fieldAdded(change, "parents", List.of(bu1.getEntityReference())); | ||||
|     fieldDeleted(change, "parents", List.of(ORG_TEAM.getEntityReference())); | ||||
|     patchEntityAndCheck(bu2, json, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change); | ||||
|   } | ||||
| 
 | ||||
|   @Test | ||||
| @ -626,11 +625,11 @@ public class TeamResourceTest extends EntityResourceTest<Team, CreateTeam> { | ||||
|     fieldUpdated(change, "isJoinable", false, true); | ||||
|     team = patchEntityAndCheck(team, json, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change); | ||||
| 
 | ||||
|     // set isJoinable to false - change from this PATCH and the previous are consolidated resulting | ||||
|     // in no change | ||||
|     json = JsonUtils.pojoToJson(team); | ||||
|     team.setIsJoinable(false); | ||||
|     patchEntityAndCheck(team, json, ADMIN_AUTH_HEADERS, NO_CHANGE, null); | ||||
|     change = getChangeDescription(team, MINOR_UPDATE); | ||||
|     fieldUpdated(change, "isJoinable", true, false); | ||||
|     patchEntityAndCheck(team, json, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change); | ||||
|   } | ||||
| 
 | ||||
|   @Test | ||||
| @ -672,10 +671,9 @@ public class TeamResourceTest extends EntityResourceTest<Team, CreateTeam> { | ||||
|     int removeDefaultRoleIndex = new Random().nextInt(roles.size()); | ||||
|     EntityReference deletedRole = team.getDefaultRoles().get(removeDefaultRoleIndex); | ||||
|     team.getDefaultRoles().remove(removeDefaultRoleIndex); | ||||
|     change = getChangeDescription(team, CHANGE_CONSOLIDATED); | ||||
|     fieldDeleted(change, "users", CommonUtil.listOf(deletedUser)); | ||||
|     change = getChangeDescription(team, MINOR_UPDATE); | ||||
|     fieldDeleted(change, "defaultRoles", CommonUtil.listOf(deletedRole)); | ||||
|     patchEntityAndCheck(team, json, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change); | ||||
|     patchEntityAndCheck(team, json, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change); | ||||
|   } | ||||
| 
 | ||||
|   @Test | ||||
| @ -725,8 +723,10 @@ public class TeamResourceTest extends EntityResourceTest<Team, CreateTeam> { | ||||
|     // resulting in no change | ||||
|     json = JsonUtils.pojoToJson(team); | ||||
|     team.withPolicies(null); | ||||
|     change = getChangeDescription(team, REVERT); | ||||
|     patchEntityAndCheck(team, json, ADMIN_AUTH_HEADERS, REVERT, change); | ||||
|     change = getChangeDescription(team, MINOR_UPDATE); | ||||
|     fieldDeleted( | ||||
|         change, "policies", List.of(POLICY1.getEntityReference(), POLICY2.getEntityReference())); | ||||
|     patchEntityAndCheck(team, json, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change); | ||||
|   } | ||||
| 
 | ||||
|   @Test | ||||
| @ -768,13 +768,11 @@ public class TeamResourceTest extends EntityResourceTest<Team, CreateTeam> { | ||||
|     fieldUpdated(change, "profile", PROFILE, profile1); | ||||
|     team = patchEntityAndCheck(team, json, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change); | ||||
| 
 | ||||
|     // Remove profile from the team - Change from this PATCH and previous are consolidated to no | ||||
|     // change | ||||
|     json = JsonUtils.pojoToJson(team); | ||||
|     team.withProfile(null); | ||||
|     change = getChangeDescription(team, CHANGE_CONSOLIDATED); | ||||
|     fieldDeleted(change, "profile", PROFILE); | ||||
|     patchEntityAndCheck(team, json, ADMIN_AUTH_HEADERS, CHANGE_CONSOLIDATED, change); | ||||
|     change = getChangeDescription(team, MINOR_UPDATE); | ||||
|     fieldDeleted(change, "profile", profile1); | ||||
|     patchEntityAndCheck(team, json, ADMIN_AUTH_HEADERS, MINOR_UPDATE, change); | ||||
|   } | ||||
| 
 | ||||
|   @Test | ||||
|  | ||||
| @ -89,7 +89,7 @@ test('Glossary', async ({ page }) => { | ||||
| 
 | ||||
|     await page.reload(); | ||||
|     const versionPageResponse = page.waitForResponse( | ||||
|       `/api/v1/glossaries/${glossary.responseData.id}/versions/0.2` | ||||
|       `/api/v1/glossaries/${glossary.responseData.id}/versions/0.3` | ||||
|     ); | ||||
|     await page.click('[data-testid="version-button"]'); | ||||
|     await versionPageResponse; | ||||
|  | ||||
| @ -173,7 +173,9 @@ test('Classification Page', async ({ page }) => { | ||||
|       ) | ||||
|     ).not.toBeVisible(); | ||||
| 
 | ||||
|     await expect(page.getByTestId('saveAssociatedTag')).not.toBeVisible(); | ||||
|     await expect(page.getByText('No Tags are available')).toBeVisible(); | ||||
| 
 | ||||
|     await expect(page.getByTestId('saveAssociatedTag')).toBeDisabled(); | ||||
| 
 | ||||
|     // Re-enable the disabled Classification
 | ||||
|     await classification.visitPage(page); | ||||
| @ -207,6 +209,7 @@ test('Classification Page', async ({ page }) => { | ||||
|   }); | ||||
| 
 | ||||
|   await test.step('Create classification with validation checks', async () => { | ||||
|     await classification.visitPage(page); | ||||
|     await page.click('[data-testid="add-classification"]'); | ||||
|     await page.waitForSelector('.ant-modal-content', { | ||||
|       state: 'visible', | ||||
|  | ||||
| @ -80,12 +80,12 @@ test('Classification version page', async ({ page }) => { | ||||
|   await patchClassificationResponse; | ||||
| 
 | ||||
|   // Verify disabled state
 | ||||
|   await page.click('[data-testid="version-button"]:has-text("0.2")'); | ||||
|   await page.click('[data-testid="version-button"]:has-text("0.3")'); | ||||
| 
 | ||||
|   await expect(page.locator('[data-testid="disabled"]')).toBeVisible(); | ||||
| 
 | ||||
|   // Toggle back to enabled
 | ||||
|   await page.click('[data-testid="version-button"]:has-text("0.2")'); | ||||
|   await page.click('[data-testid="version-button"]:has-text("0.3")'); | ||||
|   await page.click('[data-testid="manage-button"]'); | ||||
|   const patchClassificationResponse2 = page.waitForResponse( | ||||
|     `/api/v1/classifications/${classification.responseData?.id}` | ||||
| @ -94,7 +94,7 @@ test('Classification version page', async ({ page }) => { | ||||
|   await patchClassificationResponse2; | ||||
| 
 | ||||
|   // Verify enabled state
 | ||||
|   await page.click('[data-testid="version-button"]:has-text("0.2")'); | ||||
|   await page.click('[data-testid="version-button"]:has-text("0.4")'); | ||||
| 
 | ||||
|   await expect( | ||||
|     page.locator(`[data-testid="classification-${classification.data.name}"]`) | ||||
|  | ||||
| @ -153,7 +153,7 @@ entities.forEach((EntityClass) => { | ||||
|           type: 'Users', | ||||
|         }); | ||||
| 
 | ||||
|         const versionDetailResponse = page.waitForResponse(`**/versions/0.2`); | ||||
|         const versionDetailResponse = page.waitForResponse(`**/versions/0.3`); | ||||
|         await page.locator('[data-testid="version-button"]').click(); | ||||
|         await versionDetailResponse; | ||||
| 
 | ||||
| @ -169,7 +169,7 @@ entities.forEach((EntityClass) => { | ||||
| 
 | ||||
|         await assignTier(page, 'Tier1', entity.endpoint); | ||||
| 
 | ||||
|         const versionDetailResponse = page.waitForResponse(`**/versions/0.2`); | ||||
|         const versionDetailResponse = page.waitForResponse(`**/versions/0.4`); | ||||
|         await page.locator('[data-testid="version-button"]').click(); | ||||
|         await versionDetailResponse; | ||||
| 
 | ||||
| @ -210,7 +210,7 @@ entities.forEach((EntityClass) => { | ||||
| 
 | ||||
|           await expect(deletedBadge).toHaveText('Deleted'); | ||||
| 
 | ||||
|           const versionDetailResponse = page.waitForResponse(`**/versions/0.3`); | ||||
|           const versionDetailResponse = page.waitForResponse(`**/versions/0.5`); | ||||
|           await page.locator('[data-testid="version-button"]').click(); | ||||
|           await versionDetailResponse; | ||||
| 
 | ||||
|  | ||||
| @ -136,7 +136,7 @@ export const addTagToTableColumn = async ( | ||||
| 
 | ||||
|   await expect( | ||||
|     page.locator( | ||||
|       `[data-testid="classification-tags-${columnNumber}"] [data-testid="tags-container"] [data-testid="icon"]` | ||||
|       `[data-testid="classification-tags-${columnNumber}"] [data-testid="tags-container"] [data-testid="tag-${tagFqn}"]` | ||||
|     ) | ||||
|   ).toBeVisible(); | ||||
| }; | ||||
|  | ||||
| @ -13,6 +13,7 @@ | ||||
| import { CloseOutlined } from '@ant-design/icons'; | ||||
| import { | ||||
|   Button, | ||||
|   Empty, | ||||
|   Form, | ||||
|   Select, | ||||
|   SelectProps, | ||||
| @ -187,6 +188,7 @@ const AsyncSelectList: FC<AsyncSelectListProps & SelectProps> = ({ | ||||
|           <Button | ||||
|             className="update-btn" | ||||
|             data-testid="saveAssociatedTag" | ||||
|             disabled={isEmpty(tagOptions)} | ||||
|             htmlType="submit" | ||||
|             loading={isSubmitLoading} | ||||
|             size="small" | ||||
| @ -302,7 +304,18 @@ const AsyncSelectList: FC<AsyncSelectListProps & SelectProps> = ({ | ||||
|       dropdownRender={dropdownRender} | ||||
|       filterOption={false} | ||||
|       mode={mode} | ||||
|       notFoundContent={isLoading ? <Loader size="small" /> : null} | ||||
|       notFoundContent={ | ||||
|         isLoading ? ( | ||||
|           <Loader size="small" /> | ||||
|         ) : ( | ||||
|           <Empty | ||||
|             description={t('label.no-entity-available', { | ||||
|               entity: t('label.tag-plural'), | ||||
|             })} | ||||
|             image={Empty.PRESENTED_IMAGE_SIMPLE} | ||||
|           /> | ||||
|         ) | ||||
|       } | ||||
|       optionLabelProp="label" | ||||
|       style={{ width: '100%' }} | ||||
|       tagRender={customTagRender} | ||||
|  | ||||
| @ -773,6 +773,7 @@ | ||||
|     "no-description": "Keine Beschreibung", | ||||
|     "no-diff-available": "Keine Unterschiede verfügbar", | ||||
|     "no-entity": "Keine {{entity}}", | ||||
|     "no-entity-available": "No {{entity}} are available", | ||||
|     "no-entity-selected": "No {{entity}} Selected", | ||||
|     "no-matching-data-asset": "Keine passenden Datenanlagen gefunden", | ||||
|     "no-of-test": " Nr. der Tests", | ||||
|  | ||||
| @ -773,6 +773,7 @@ | ||||
|     "no-description": "No description", | ||||
|     "no-diff-available": "No diff available", | ||||
|     "no-entity": "No {{entity}}", | ||||
|     "no-entity-available": "No {{entity}} are available", | ||||
|     "no-entity-selected": "No {{entity}} Selected", | ||||
|     "no-matching-data-asset": "No matching data assets found", | ||||
|     "no-of-test": " No. of Test", | ||||
|  | ||||
| @ -773,6 +773,7 @@ | ||||
|     "no-description": "Sin descripción", | ||||
|     "no-diff-available": "Sin diferencia disponible", | ||||
|     "no-entity": "No hay {{entity}}", | ||||
|     "no-entity-available": "No {{entity}} are available", | ||||
|     "no-entity-selected": "No {{entity}} Selected", | ||||
|     "no-matching-data-asset": "No se encontraron activos de datos coincidentes", | ||||
|     "no-of-test": "No. de prueba", | ||||
|  | ||||
| @ -773,6 +773,7 @@ | ||||
|     "no-description": "Aucune description", | ||||
|     "no-diff-available": "Aucune différence disponible", | ||||
|     "no-entity": "Pas de {{entity}}", | ||||
|     "no-entity-available": "No {{entity}} are available", | ||||
|     "no-entity-selected": "No {{entity}} Selected", | ||||
|     "no-matching-data-asset": "Aucun actif de données trouvé", | ||||
|     "no-of-test": " No. de Tests", | ||||
|  | ||||
| @ -773,6 +773,7 @@ | ||||
|     "no-description": "-", | ||||
|     "no-diff-available": "אין הבדל זמין", | ||||
|     "no-entity": "אין {{entity}}", | ||||
|     "no-entity-available": "No {{entity}} are available", | ||||
|     "no-entity-selected": "No {{entity}} Selected", | ||||
|     "no-matching-data-asset": "לא נמצאו נכסי נתונים תואמים", | ||||
|     "no-of-test": "מספר הבדיקות", | ||||
|  | ||||
| @ -773,6 +773,7 @@ | ||||
|     "no-description": "説明がありません", | ||||
|     "no-diff-available": "差分を見ることはできません", | ||||
|     "no-entity": "No {{entity}}", | ||||
|     "no-entity-available": "No {{entity}} are available", | ||||
|     "no-entity-selected": "No {{entity}} Selected", | ||||
|     "no-matching-data-asset": "マッチするデータアセットはありません", | ||||
|     "no-of-test": " テスト番号", | ||||
|  | ||||
| @ -773,6 +773,7 @@ | ||||
|     "no-description": "Geen beschrijving", | ||||
|     "no-diff-available": "Geen verschil beschikbaar", | ||||
|     "no-entity": "Geen {{entity}}", | ||||
|     "no-entity-available": "No {{entity}} are available", | ||||
|     "no-entity-selected": "No {{entity}} Selected", | ||||
|     "no-matching-data-asset": "Geen overeenkomende data-assets gevonden", | ||||
|     "no-of-test": " Aantal tests", | ||||
|  | ||||
| @ -773,6 +773,7 @@ | ||||
|     "no-description": "بدون توضیح", | ||||
|     "no-diff-available": "هیچ تفاوتی موجود نیست", | ||||
|     "no-entity": "هیچ {{entity}}", | ||||
|     "no-entity-available": "No {{entity}} are available", | ||||
|     "no-entity-selected": "هیچ {{entity}} انتخاب نشده", | ||||
|     "no-matching-data-asset": "هیچ دارایی دادهی منطبق یافت نشد", | ||||
|     "no-of-test": "تعداد تست", | ||||
|  | ||||
| @ -773,6 +773,7 @@ | ||||
|     "no-description": "Sem descrição", | ||||
|     "no-diff-available": "Nenhuma diferença disponível", | ||||
|     "no-entity": "Nenhum(a) {{entity}}", | ||||
|     "no-entity-available": "No {{entity}} are available", | ||||
|     "no-entity-selected": "No {{entity}} Selected", | ||||
|     "no-matching-data-asset": "Nenhum ativo de dados correspondente encontrado", | ||||
|     "no-of-test": " Nº de Teste", | ||||
|  | ||||
| @ -773,6 +773,7 @@ | ||||
|     "no-description": "Нет описания", | ||||
|     "no-diff-available": "Нет различий", | ||||
|     "no-entity": "{{entity}} отсутствует", | ||||
|     "no-entity-available": "No {{entity}} are available", | ||||
|     "no-entity-selected": "No {{entity}} Selected", | ||||
|     "no-matching-data-asset": "Подходящие объекты данных не найдены", | ||||
|     "no-of-test": "№ теста", | ||||
|  | ||||
| @ -773,6 +773,7 @@ | ||||
|     "no-description": "无描述", | ||||
|     "no-diff-available": "没有可用的差异", | ||||
|     "no-entity": "没有{{entity}}", | ||||
|     "no-entity-available": "No {{entity}} are available", | ||||
|     "no-entity-selected": "No {{entity}} Selected", | ||||
|     "no-matching-data-asset": "未找到匹配的数据资产", | ||||
|     "no-of-test": "测试数量", | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Sriharsha Chintalapani
						Sriharsha Chintalapani