mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-11-02 11:39:12 +00:00
Fixes: Drive Service (#23637)
* fix: added missing fields * fix: java checkstyle and add mimeType * Fix Data Asset Headers for drive assets --------- Co-authored-by: Aniket Katkar <aniketkatkar97@gmail.com>
This commit is contained in:
parent
1adc09f07e
commit
6f47baa264
@ -146,13 +146,71 @@ public class DirectoryRepository extends EntityRepository<Directory> {
|
||||
public void clearFields(Directory directory, EntityUtil.Fields fields) {
|
||||
directory.withUsageSummary(
|
||||
fields.contains("usageSummary") ? directory.getUsageSummary() : null);
|
||||
directory.withNumberOfFiles(
|
||||
fields.contains("numberOfFiles") ? directory.getNumberOfFiles() : null);
|
||||
directory.withNumberOfSubDirectories(
|
||||
fields.contains("numberOfSubDirectories") ? directory.getNumberOfSubDirectories() : null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFields(Directory directory, EntityUtil.Fields fields) {
|
||||
directory.withService(getService(directory));
|
||||
directory.withParent(getParentDirectory(directory));
|
||||
directory.withChildren(fields.contains("children") ? getChildrenRefs(directory) : null);
|
||||
|
||||
// Calculate and set directory statistics
|
||||
if (fields.contains("children")
|
||||
|| fields.contains("numberOfFiles")
|
||||
|| fields.contains("numberOfSubDirectories")
|
||||
|| fields.contains("totalSize")) {
|
||||
List<EntityReference> children = getChildrenRefs(directory);
|
||||
directory.withChildren(fields.contains("children") ? children : null);
|
||||
|
||||
// Calculate statistics from children
|
||||
if (children != null && !children.isEmpty()) {
|
||||
int fileCount = 0;
|
||||
int dirCount = 0;
|
||||
long totalSize = 0L;
|
||||
|
||||
for (EntityReference child : children) {
|
||||
if (FILE.equals(child.getType())) {
|
||||
fileCount++;
|
||||
// Get file size if available
|
||||
try {
|
||||
org.openmetadata.schema.entity.data.File file =
|
||||
Entity.getEntity(child, "", Include.NON_DELETED);
|
||||
if (file.getSize() != null) {
|
||||
totalSize += file.getSize();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Ignore if file can't be loaded
|
||||
}
|
||||
} else if (DIRECTORY.equals(child.getType())) {
|
||||
dirCount++;
|
||||
} else if (SPREADSHEET.equals(child.getType())) {
|
||||
fileCount++; // Count spreadsheets as files
|
||||
try {
|
||||
org.openmetadata.schema.entity.data.Spreadsheet spreadsheet =
|
||||
Entity.getEntity(child, "", Include.NON_DELETED);
|
||||
if (spreadsheet.getSize() != null) {
|
||||
totalSize += spreadsheet.getSize();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Ignore if spreadsheet can't be loaded
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
directory.withNumberOfFiles(fileCount);
|
||||
directory.withNumberOfSubDirectories(dirCount);
|
||||
// Convert long to Integer, checking for overflow
|
||||
directory.withTotalSize(
|
||||
totalSize > 0
|
||||
? (totalSize > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) totalSize)
|
||||
: null);
|
||||
}
|
||||
} else {
|
||||
directory.withChildren(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -47,7 +47,7 @@ import org.openmetadata.schema.type.csv.CsvHeader;
|
||||
import org.openmetadata.schema.type.csv.CsvImportResult;
|
||||
import org.openmetadata.service.Entity;
|
||||
import org.openmetadata.service.exception.EntityNotFoundException;
|
||||
import org.openmetadata.service.resources.services.DriveServiceResource;
|
||||
import org.openmetadata.service.resources.services.drive.DriveServiceResource;
|
||||
import org.openmetadata.service.util.EntityUtil;
|
||||
import org.openmetadata.service.util.FullyQualifiedName;
|
||||
|
||||
|
||||
@ -263,7 +263,9 @@ public class SpreadsheetRepository extends EntityRepository<Spreadsheet> {
|
||||
new CsvHeader().withName("domain"),
|
||||
new CsvHeader().withName("dataProducts"),
|
||||
new CsvHeader().withName("experts"),
|
||||
new CsvHeader().withName("reviewers"));
|
||||
new CsvHeader().withName("reviewers"),
|
||||
new CsvHeader().withName("createdTime"),
|
||||
new CsvHeader().withName("modifiedTime"));
|
||||
|
||||
DOCUMENTATION = new CsvDocumentation().withHeaders(HEADERS).withSummary("Spreadsheet");
|
||||
}
|
||||
@ -339,7 +341,11 @@ public class SpreadsheetRepository extends EntityRepository<Spreadsheet> {
|
||||
Pair.of(9, TagLabel.TagSource.CLASSIFICATION),
|
||||
Pair.of(10, TagLabel.TagSource.GLOSSARY))))
|
||||
.withDomains(getDomains(printer, csvRecord, 11))
|
||||
.withDataProducts(getDataProducts(printer, csvRecord, 12));
|
||||
.withDataProducts(getDataProducts(printer, csvRecord, 12))
|
||||
.withCreatedTime(
|
||||
nullOrEmpty(csvRecord.get(15)) ? null : Long.parseLong(csvRecord.get(15)))
|
||||
.withModifiedTime(
|
||||
nullOrEmpty(csvRecord.get(16)) ? null : Long.parseLong(csvRecord.get(16)));
|
||||
|
||||
if (processRecord) {
|
||||
createEntity(printer, csvRecord, newSpreadsheet, SPREADSHEET);
|
||||
@ -353,7 +359,11 @@ public class SpreadsheetRepository extends EntityRepository<Spreadsheet> {
|
||||
addField(recordList, entity.getDisplayName());
|
||||
addField(recordList, entity.getDescription());
|
||||
addField(recordList, entity.getDirectory().getFullyQualifiedName());
|
||||
addField(recordList, entity.getMimeType().toString());
|
||||
addField(recordList, entity.getMimeType() != null ? entity.getMimeType().toString() : "");
|
||||
addField(
|
||||
recordList, entity.getCreatedTime() != null ? entity.getCreatedTime().toString() : "");
|
||||
addField(
|
||||
recordList, entity.getModifiedTime() != null ? entity.getModifiedTime().toString() : "");
|
||||
addField(recordList, entity.getPath());
|
||||
addField(recordList, entity.getSize() != null ? entity.getSize().toString() : "");
|
||||
addField(recordList, entity.getFileVersion());
|
||||
@ -415,6 +425,8 @@ public class SpreadsheetRepository extends EntityRepository<Spreadsheet> {
|
||||
@Override
|
||||
public void entitySpecificUpdate(boolean consolidatingChanges) {
|
||||
recordChange("mimeType", original.getMimeType(), updated.getMimeType());
|
||||
recordChange("createdTime", original.getCreatedTime(), updated.getCreatedTime());
|
||||
recordChange("modifiedTime", original.getModifiedTime(), updated.getModifiedTime());
|
||||
recordChange("path", original.getPath(), updated.getPath());
|
||||
recordChange("driveFileId", original.getDriveFileId(), updated.getDriveFileId());
|
||||
recordChange("size", original.getSize(), updated.getSize());
|
||||
|
||||
@ -18,6 +18,7 @@ public class DirectoryMapper implements EntityMapper<Directory, CreateDirectory>
|
||||
: null)
|
||||
.withPath(create.getPath())
|
||||
.withIsShared(create.getIsShared())
|
||||
.withSourceUrl(create.getSourceUrl());
|
||||
.withSourceUrl(create.getSourceUrl())
|
||||
.withDirectoryType(create.getDirectoryType());
|
||||
}
|
||||
}
|
||||
|
||||
@ -76,7 +76,7 @@ import org.openmetadata.service.security.Authorizer;
|
||||
public class DirectoryResource extends EntityResource<Directory, DirectoryRepository> {
|
||||
public static final String COLLECTION_PATH = "v1/drives/directories/";
|
||||
static final String FIELDS =
|
||||
"owners,children,parent,usageSummary,tags,extension,domains,sourceHash,lifeCycle,votes,followers";
|
||||
"owners,children,parent,usageSummary,tags,extension,domains,sourceHash,lifeCycle,votes,followers,numberOfFiles,numberOfSubDirectories,totalSize,directoryType";
|
||||
private final DirectoryMapper mapper = new DirectoryMapper();
|
||||
|
||||
@Override
|
||||
|
||||
@ -18,7 +18,9 @@ public class SpreadsheetMapper implements EntityMapper<Spreadsheet, CreateSpread
|
||||
.withDriveFileId(create.getDriveFileId())
|
||||
.withSize(create.getSize())
|
||||
.withFileVersion(create.getFileVersion())
|
||||
.withSourceUrl(create.getSourceUrl());
|
||||
.withSourceUrl(create.getSourceUrl())
|
||||
.withCreatedTime(create.getCreatedTime())
|
||||
.withModifiedTime(create.getModifiedTime());
|
||||
|
||||
// Set directory from parent if provided
|
||||
if (create.getParent() != null) {
|
||||
|
||||
@ -74,7 +74,7 @@ import org.openmetadata.service.security.Authorizer;
|
||||
public class SpreadsheetResource extends EntityResource<Spreadsheet, SpreadsheetRepository> {
|
||||
public static final String COLLECTION_PATH = "v1/drives/spreadsheets/";
|
||||
static final String FIELDS =
|
||||
"owners,directory,worksheets,usageSummary,tags,extension,domains,sourceHash,lifeCycle,votes,followers";
|
||||
"owners,directory,worksheets,usageSummary,tags,extension,domains,sourceHash,lifeCycle,votes,followers,mimeType,createdTime,modifiedTime";
|
||||
private final SpreadsheetMapper mapper = new SpreadsheetMapper();
|
||||
|
||||
@Override
|
||||
|
||||
@ -73,7 +73,7 @@ import org.openmetadata.service.security.Authorizer;
|
||||
public class WorksheetResource extends EntityResource<Worksheet, WorksheetRepository> {
|
||||
public static final String COLLECTION_PATH = "v1/drives/worksheets/";
|
||||
static final String FIELDS =
|
||||
"owners,spreadsheet,columns,sampleData,usageSummary,tags,extension,domains,sourceHash,lifeCycle,votes,followers";
|
||||
"owners,spreadsheet,columns,sampleData,usageSummary,tags,extension,domains,sourceHash,lifeCycle,votes,followers,rowCount";
|
||||
private final WorksheetMapper mapper = new WorksheetMapper();
|
||||
|
||||
@Override
|
||||
|
||||
@ -0,0 +1,15 @@
|
||||
package org.openmetadata.service.resources.services.drive;
|
||||
|
||||
import org.openmetadata.schema.api.services.CreateDriveService;
|
||||
import org.openmetadata.schema.entity.services.DriveService;
|
||||
import org.openmetadata.service.mapper.EntityMapper;
|
||||
|
||||
public class DriveServiceMapper implements EntityMapper<DriveService, CreateDriveService> {
|
||||
@Override
|
||||
public DriveService createToEntity(CreateDriveService create, String user) {
|
||||
return copy(new DriveService(), create, user)
|
||||
.withServiceType(create.getServiceType())
|
||||
.withConnection(create.getConnection())
|
||||
.withIngestionRunner(create.getIngestionRunner());
|
||||
}
|
||||
}
|
||||
@ -11,7 +11,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.openmetadata.service.resources.services;
|
||||
package org.openmetadata.service.resources.services.drive;
|
||||
|
||||
import io.swagger.v3.oas.annotations.ExternalDocumentation;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
@ -64,6 +64,7 @@ import org.openmetadata.service.Entity;
|
||||
import org.openmetadata.service.jdbi3.DriveServiceRepository;
|
||||
import org.openmetadata.service.limits.Limits;
|
||||
import org.openmetadata.service.resources.Collection;
|
||||
import org.openmetadata.service.resources.services.ServiceEntityResource;
|
||||
import org.openmetadata.service.security.Authorizer;
|
||||
import org.openmetadata.service.security.policyevaluator.OperationContext;
|
||||
|
||||
@ -81,6 +82,7 @@ public class DriveServiceResource
|
||||
extends ServiceEntityResource<DriveService, DriveServiceRepository, DriveConnection> {
|
||||
public static final String COLLECTION_PATH = "v1/services/driveServices/";
|
||||
public static final String FIELDS = "pipelines,owners,tags,domains,followers";
|
||||
private final DriveServiceMapper driveServiceMapper = new DriveServiceMapper();
|
||||
|
||||
@Override
|
||||
public DriveService addHref(UriInfo uriInfo, DriveService service) {
|
||||
@ -660,10 +662,7 @@ public class DriveServiceResource
|
||||
}
|
||||
|
||||
private DriveService getService(CreateDriveService create, String user) {
|
||||
return repository
|
||||
.copy(new DriveService(), create, user)
|
||||
.withServiceType(create.getServiceType())
|
||||
.withConnection(create.getConnection());
|
||||
return driveServiceMapper.createToEntity(create, user);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -46,6 +46,7 @@ import org.openmetadata.schema.services.connections.database.UnityCatalogConnect
|
||||
import org.openmetadata.schema.services.connections.database.datalake.GCSConfig;
|
||||
import org.openmetadata.schema.services.connections.database.deltalake.StorageConfig;
|
||||
import org.openmetadata.schema.services.connections.database.iceberg.IcebergFileSystem;
|
||||
import org.openmetadata.schema.services.connections.drive.GoogleDriveConnection;
|
||||
import org.openmetadata.schema.services.connections.mlmodel.VertexAIConnection;
|
||||
import org.openmetadata.schema.services.connections.pipeline.AirflowConnection;
|
||||
import org.openmetadata.schema.services.connections.pipeline.MatillionConnection;
|
||||
@ -78,6 +79,7 @@ public final class ClassConverterFactory {
|
||||
Map.entry(GCSConfig.class, new GCPConfigClassConverter()),
|
||||
Map.entry(GCPCredentials.class, new GcpCredentialsClassConverter()),
|
||||
Map.entry(GCSConnection.class, new GcpConnectionClassConverter()),
|
||||
Map.entry(GoogleDriveConnection.class, new GoogleDriveConnectionClassConverter()),
|
||||
Map.entry(HiveConnection.class, new HiveConnectionClassConverter()),
|
||||
Map.entry(IcebergConnection.class, new IcebergConnectionClassConverter()),
|
||||
Map.entry(IcebergFileSystem.class, new IcebergFileSystemClassConverter()),
|
||||
|
||||
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2021 Collate
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.openmetadata.service.secrets.converter;
|
||||
|
||||
import java.util.List;
|
||||
import org.openmetadata.schema.security.credentials.GCPCredentials;
|
||||
import org.openmetadata.schema.services.connections.drive.GoogleDriveConnection;
|
||||
import org.openmetadata.schema.utils.JsonUtils;
|
||||
|
||||
/** Converter class to get a `GoogleDriveConnection` object. */
|
||||
public class GoogleDriveConnectionClassConverter extends ClassConverter {
|
||||
|
||||
public GoogleDriveConnectionClassConverter() {
|
||||
super(GoogleDriveConnection.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object convert(Object object) {
|
||||
GoogleDriveConnection googleDriveConnection =
|
||||
(GoogleDriveConnection) JsonUtils.convertValue(object, this.clazz);
|
||||
|
||||
tryToConvertOrFail(googleDriveConnection.getCredentials(), List.of(GCPCredentials.class))
|
||||
.ifPresent(obj -> googleDriveConnection.setCredentials((GCPCredentials) obj));
|
||||
|
||||
return googleDriveConnection;
|
||||
}
|
||||
}
|
||||
@ -55,6 +55,7 @@ import org.openmetadata.schema.type.FileType;
|
||||
import org.openmetadata.schema.utils.JsonUtils;
|
||||
import org.openmetadata.schema.utils.ResultList;
|
||||
import org.openmetadata.service.Entity;
|
||||
import org.openmetadata.service.resources.services.drive.DriveServiceResource;
|
||||
import org.openmetadata.service.util.TestUtils;
|
||||
|
||||
@Slf4j
|
||||
|
||||
@ -5,7 +5,9 @@
|
||||
"description": "Create Spreadsheet entity request",
|
||||
"type": "object",
|
||||
"javaType": "org.openmetadata.schema.api.data.CreateSpreadsheet",
|
||||
"javaInterfaces": ["org.openmetadata.schema.CreateEntity"],
|
||||
"javaInterfaces": [
|
||||
"org.openmetadata.schema.CreateEntity"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"description": "Name that identifies this spreadsheet.",
|
||||
@ -92,8 +94,19 @@
|
||||
"extension": {
|
||||
"description": "Entity extension data with custom attributes added to the entity.",
|
||||
"$ref": "../../type/basic.json#/definitions/entityExtension"
|
||||
},
|
||||
"createdTime": {
|
||||
"description": "Spreadsheet creation timestamp",
|
||||
"$ref": "../../type/basic.json#/definitions/timestamp"
|
||||
},
|
||||
"modifiedTime": {
|
||||
"description": "Last modification timestamp",
|
||||
"$ref": "../../type/basic.json#/definitions/timestamp"
|
||||
}
|
||||
},
|
||||
"required": ["name", "service"],
|
||||
"required": [
|
||||
"name",
|
||||
"service"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
@ -5,7 +5,9 @@
|
||||
"description": "Create Drive Service entity request",
|
||||
"type": "object",
|
||||
"javaType": "org.openmetadata.schema.api.services.CreateDriveService",
|
||||
"javaInterfaces": ["org.openmetadata.schema.CreateEntity"],
|
||||
"javaInterfaces": [
|
||||
"org.openmetadata.schema.CreateEntity"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"description": "Name that identifies this drive service.",
|
||||
@ -53,8 +55,15 @@
|
||||
"$ref": "../../type/basic.json#/definitions/fullyQualifiedEntityName"
|
||||
},
|
||||
"default": null
|
||||
},
|
||||
"ingestionRunner": {
|
||||
"description": "The ingestion agent responsible for executing the ingestion pipeline.",
|
||||
"$ref": "../../type/entityReference.json"
|
||||
}
|
||||
},
|
||||
"required": ["name", "serviceType"],
|
||||
"required": [
|
||||
"name",
|
||||
"serviceType"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
@ -14,6 +14,10 @@
|
||||
* Create Spreadsheet entity request
|
||||
*/
|
||||
export interface CreateSpreadsheet {
|
||||
/**
|
||||
* Spreadsheet creation timestamp
|
||||
*/
|
||||
createdTime?: number;
|
||||
/**
|
||||
* List of fully qualified names of data products this entity is part of.
|
||||
*/
|
||||
@ -50,6 +54,10 @@ export interface CreateSpreadsheet {
|
||||
* MIME type of the spreadsheet file
|
||||
*/
|
||||
mimeType?: SpreadsheetMIMEType;
|
||||
/**
|
||||
* Last modification timestamp
|
||||
*/
|
||||
modifiedTime?: number;
|
||||
/**
|
||||
* Name that identifies this spreadsheet.
|
||||
*/
|
||||
|
||||
@ -31,6 +31,10 @@ export interface CreateDriveService {
|
||||
* Fully qualified names of the domains the Drive Service belongs to.
|
||||
*/
|
||||
domains?: string[];
|
||||
/**
|
||||
* The ingestion agent responsible for executing the ingestion pipeline.
|
||||
*/
|
||||
ingestionRunner?: EntityReference;
|
||||
/**
|
||||
* Name that identifies this drive service.
|
||||
*/
|
||||
@ -293,14 +297,16 @@ export enum DriveServiceType {
|
||||
}
|
||||
|
||||
/**
|
||||
* Owners of this Drive service.
|
||||
* The ingestion agent responsible for executing the ingestion pipeline.
|
||||
*
|
||||
* This schema defines the EntityReferenceList type used for referencing an entity.
|
||||
* This schema defines the EntityReference type used for referencing an entity.
|
||||
* EntityReference is used for capturing relationships from one entity to another. For
|
||||
* example, a table has an attribute called database of type EntityReference that captures
|
||||
* the relationship of a table `belongs to a` database.
|
||||
*
|
||||
* This schema defines the EntityReference type used for referencing an entity.
|
||||
* Owners of this Drive service.
|
||||
*
|
||||
* This schema defines the EntityReferenceList type used for referencing an entity.
|
||||
* EntityReference is used for capturing relationships from one entity to another. For
|
||||
* example, a table has an attribute called database of type EntityReference that captures
|
||||
* the relationship of a table `belongs to a` database.
|
||||
|
||||
@ -1608,6 +1608,7 @@
|
||||
"sub-domain-lowercase-plural": "subdomains",
|
||||
"sub-domain-plural": "Subdomains",
|
||||
"sub-team-plural": "Unter-Teams",
|
||||
"subdirectory-plural": "Unterverzeichnisse",
|
||||
"submit": "Einreichen",
|
||||
"subscription": "Subscription",
|
||||
"success": "Erfolg",
|
||||
|
||||
@ -1608,6 +1608,7 @@
|
||||
"sub-domain-lowercase-plural": "sub domains",
|
||||
"sub-domain-plural": "Sub Domains",
|
||||
"sub-team-plural": "Sub Teams",
|
||||
"subdirectory-plural": "Subdirectories",
|
||||
"submit": "Submit",
|
||||
"subscription": "Subscription",
|
||||
"success": "Success",
|
||||
|
||||
@ -1608,6 +1608,7 @@
|
||||
"sub-domain-lowercase-plural": "subdominios",
|
||||
"sub-domain-plural": "Subdominios",
|
||||
"sub-team-plural": "Subequipos",
|
||||
"subdirectory-plural": "Subdirectorios",
|
||||
"submit": "Enviar",
|
||||
"subscription": "Subscripción",
|
||||
"success": "Éxito",
|
||||
|
||||
@ -1608,6 +1608,7 @@
|
||||
"sub-domain-lowercase-plural": "sous-domaines",
|
||||
"sub-domain-plural": "Sous-Domaines",
|
||||
"sub-team-plural": "Sous-Équipes",
|
||||
"subdirectory-plural": "Sous-répertoires",
|
||||
"submit": "Soumettre",
|
||||
"subscription": "Subscription",
|
||||
"success": "Succès",
|
||||
|
||||
@ -1608,6 +1608,7 @@
|
||||
"sub-domain-lowercase-plural": "subdominios",
|
||||
"sub-domain-plural": "Subdominios",
|
||||
"sub-team-plural": "Subequipos",
|
||||
"subdirectory-plural": "Subdirectorios",
|
||||
"submit": "Enviar",
|
||||
"subscription": "Subscrición",
|
||||
"success": "Éxito",
|
||||
|
||||
@ -1608,6 +1608,7 @@
|
||||
"sub-domain-lowercase-plural": "תתי-תחומים",
|
||||
"sub-domain-plural": "תתי-תחומים",
|
||||
"sub-team-plural": "תתי-צוותים",
|
||||
"subdirectory-plural": "תתי-תיקיות",
|
||||
"submit": "שלח",
|
||||
"subscription": "מינוי",
|
||||
"success": "הצלחה",
|
||||
|
||||
@ -1608,6 +1608,7 @@
|
||||
"sub-domain-lowercase-plural": "サブドメイン",
|
||||
"sub-domain-plural": "サブドメイン",
|
||||
"sub-team-plural": "サブチーム",
|
||||
"subdirectory-plural": "サブディレクトリ",
|
||||
"submit": "送信",
|
||||
"subscription": "サブスクリプション",
|
||||
"success": "成功",
|
||||
|
||||
@ -1608,6 +1608,7 @@
|
||||
"sub-domain-lowercase-plural": "하위 도메인들",
|
||||
"sub-domain-plural": "하위 도메인들",
|
||||
"sub-team-plural": "하위 팀들",
|
||||
"subdirectory-plural": "하위 디렉토리",
|
||||
"submit": "제출",
|
||||
"subscription": "구독",
|
||||
"success": "성공",
|
||||
|
||||
@ -1608,6 +1608,7 @@
|
||||
"sub-domain-lowercase-plural": "उप डोमेन्स",
|
||||
"sub-domain-plural": "उप डोमेन्स",
|
||||
"sub-team-plural": "उप टीम्स",
|
||||
"subdirectory-plural": "उपनिर्देशिका",
|
||||
"submit": "प्रस्तुत करा",
|
||||
"subscription": "सदस्यता",
|
||||
"success": "यश",
|
||||
|
||||
@ -1608,6 +1608,7 @@
|
||||
"sub-domain-lowercase-plural": "subdomeinen",
|
||||
"sub-domain-plural": "Subdomeinen",
|
||||
"sub-team-plural": "Subteams",
|
||||
"subdirectory-plural": "Submappen",
|
||||
"submit": "Indienen",
|
||||
"subscription": "Abonnement",
|
||||
"success": "Succes",
|
||||
|
||||
@ -1608,6 +1608,7 @@
|
||||
"sub-domain-lowercase-plural": "زیر دامنهها",
|
||||
"sub-domain-plural": "زیر دامنهها",
|
||||
"sub-team-plural": "زیر تیمها",
|
||||
"subdirectory-plural": "زیرشاخهها",
|
||||
"submit": "ارسال",
|
||||
"subscription": "اشتراک",
|
||||
"success": "موفقیت",
|
||||
|
||||
@ -1608,6 +1608,7 @@
|
||||
"sub-domain-lowercase-plural": "subdomínios",
|
||||
"sub-domain-plural": "Subdomínios",
|
||||
"sub-team-plural": "Subequipes",
|
||||
"subdirectory-plural": "Subdiretórios",
|
||||
"submit": "Enviar",
|
||||
"subscription": "Assinatura",
|
||||
"success": "Sucesso",
|
||||
|
||||
@ -1608,6 +1608,7 @@
|
||||
"sub-domain-lowercase-plural": "subdomínios",
|
||||
"sub-domain-plural": "Subdomínios",
|
||||
"sub-team-plural": "Subequipas",
|
||||
"subdirectory-plural": "Subdiretórios",
|
||||
"submit": "Enviar",
|
||||
"subscription": "Assinatura",
|
||||
"success": "Sucesso",
|
||||
|
||||
@ -1608,6 +1608,7 @@
|
||||
"sub-domain-lowercase-plural": "поддомены",
|
||||
"sub-domain-plural": "Поддомены",
|
||||
"sub-team-plural": "Подгруппы",
|
||||
"subdirectory-plural": "Подкаталоги",
|
||||
"submit": "Подтвердить",
|
||||
"subscription": "Подписка",
|
||||
"success": "Успешно",
|
||||
|
||||
@ -1608,6 +1608,7 @@
|
||||
"sub-domain-lowercase-plural": "โดเมนย่อยหลายรายการ",
|
||||
"sub-domain-plural": "โดเมนย่อยหลายรายการ",
|
||||
"sub-team-plural": "ทีมย่อย",
|
||||
"subdirectory-plural": "ไดเรกทอรีย่อยหลายรายการ",
|
||||
"submit": "ส่ง",
|
||||
"subscription": "การสมัครสมาชิก",
|
||||
"success": "สำเร็จ",
|
||||
|
||||
@ -1608,6 +1608,7 @@
|
||||
"sub-domain-lowercase-plural": "alt alan adları",
|
||||
"sub-domain-plural": "Alt Alan Adları",
|
||||
"sub-team-plural": "Alt Takımlar",
|
||||
"subdirectory-plural": "Alt dizinler",
|
||||
"submit": "Gönder",
|
||||
"subscription": "Abonelik",
|
||||
"success": "Başarılı",
|
||||
|
||||
@ -1608,6 +1608,7 @@
|
||||
"sub-domain-lowercase-plural": "子域",
|
||||
"sub-domain-plural": "子域",
|
||||
"sub-team-plural": "子团队",
|
||||
"subdirectory-plural": "子目录",
|
||||
"submit": "提交",
|
||||
"subscription": "订阅",
|
||||
"success": "成功",
|
||||
|
||||
@ -1608,6 +1608,7 @@
|
||||
"sub-domain-lowercase-plural": "子領域",
|
||||
"sub-domain-plural": "子領域",
|
||||
"sub-team-plural": "子團隊",
|
||||
"subdirectory-plural": "子目錄",
|
||||
"submit": "提交",
|
||||
"subscription": "訂閱",
|
||||
"success": "成功",
|
||||
|
||||
@ -11,8 +11,14 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { render } from '@testing-library/react';
|
||||
import { Tooltip, Typography } from 'antd';
|
||||
import React from 'react';
|
||||
import { EntityType } from '../enums/entity.enum';
|
||||
import {
|
||||
Spreadsheet,
|
||||
SpreadsheetMIMEType,
|
||||
} from '../generated/entity/data/spreadsheet';
|
||||
import { mockContainerData } from '../mocks/ContainerVersion.mock';
|
||||
import { MOCK_DASHBOARD_DATA_MODEL } from '../mocks/DashboardDataModel.mock';
|
||||
import { mockDashboardData } from '../mocks/dashboardVersion.mock';
|
||||
@ -35,13 +41,14 @@ import { mockStoredProcedureData } from '../mocks/StoredProcedure.mock';
|
||||
import { MOCK_TABLE } from '../mocks/TableData.mock';
|
||||
import { mockTopicData } from '../mocks/TopicVersion.mock';
|
||||
import {
|
||||
ExtraInfoLabel,
|
||||
getDataAssetsHeaderInfo,
|
||||
getEntityExtraInfoLength,
|
||||
} from './DataAssetsHeader.utils';
|
||||
|
||||
// Mock only ExtraInfoLink, not ExtraInfoLabel as we want to test it
|
||||
jest.mock('./DataAssetsHeader.utils', () => ({
|
||||
...jest.requireActual('./DataAssetsHeader.utils'),
|
||||
ExtraInfoLabel: jest.fn().mockImplementation(({ value }) => value),
|
||||
ExtraInfoLink: jest.fn().mockImplementation(({ value }) => value),
|
||||
}));
|
||||
jest.mock('./EntityUtils', () => ({
|
||||
@ -87,6 +94,17 @@ jest.mock('./TableUtils', () => ({
|
||||
getUsagePercentile: jest.fn().mockReturnValue('getUsagePercentile'),
|
||||
}));
|
||||
|
||||
jest.mock('./date-time/DateTimeUtils', () => ({
|
||||
...jest.requireActual('./date-time/DateTimeUtils'),
|
||||
formatDateTime: jest
|
||||
.fn()
|
||||
.mockImplementation((timestamp) => `formatted-${timestamp}`),
|
||||
getEpochMillisForPastDays: jest
|
||||
.fn()
|
||||
.mockImplementation((days) => Date.now() - days * 24 * 60 * 60 * 1000),
|
||||
getCurrentMillis: jest.fn().mockReturnValue(Date.now()),
|
||||
}));
|
||||
|
||||
jest.mock('../constants/constants', () => ({
|
||||
...jest.requireActual('../constants/constants'),
|
||||
NO_DATA_PLACEHOLDER: jest.fn().mockReturnValue('---'),
|
||||
@ -506,6 +524,76 @@ describe('Tests for DataAssetsHeaderUtils', () => {
|
||||
);
|
||||
});
|
||||
|
||||
// Test for Spreadsheet entity
|
||||
it('Function getDataAssetsHeaderInfo should return data for Spreadsheet entity', () => {
|
||||
const mockSpreadsheet: Spreadsheet = {
|
||||
id: 'spreadsheet-123',
|
||||
name: 'test-spreadsheet',
|
||||
fullyQualifiedName: 'service.directory.test-spreadsheet',
|
||||
mimeType:
|
||||
'application/vnd.google-apps.spreadsheet' as SpreadsheetMIMEType,
|
||||
createdTime: 1609459200000,
|
||||
modifiedTime: 1640995200000,
|
||||
service: {
|
||||
id: 'service-123',
|
||||
name: 'google-drive',
|
||||
type: 'driveService',
|
||||
},
|
||||
};
|
||||
|
||||
const assetData = getDataAssetsHeaderInfo(
|
||||
EntityType.SPREADSHEET,
|
||||
mockSpreadsheet,
|
||||
'test-spreadsheet',
|
||||
[]
|
||||
);
|
||||
|
||||
// contains all breadcrumbs
|
||||
expect(assetData.breadcrumbs).toEqual([{ name: 'entityName', url: 'url' }]);
|
||||
|
||||
// contains extra data
|
||||
expect(JSON.stringify(assetData.extraInfo)).toContain('label.mime-type');
|
||||
expect(JSON.stringify(assetData.extraInfo)).toContain(
|
||||
'application/vnd.google-apps.spreadsheet'
|
||||
);
|
||||
|
||||
expect(JSON.stringify(assetData.extraInfo)).toContain('label.created-time');
|
||||
expect(JSON.stringify(assetData.extraInfo)).toContain(
|
||||
'formatted-1609459200000'
|
||||
);
|
||||
|
||||
expect(JSON.stringify(assetData.extraInfo)).toContain(
|
||||
'label.modified-time'
|
||||
);
|
||||
expect(JSON.stringify(assetData.extraInfo)).toContain(
|
||||
'formatted-1640995200000'
|
||||
);
|
||||
|
||||
// Test with missing optional data
|
||||
const assetWithNoExtraData = getDataAssetsHeaderInfo(
|
||||
EntityType.SPREADSHEET,
|
||||
{
|
||||
...mockSpreadsheet,
|
||||
mimeType: undefined,
|
||||
createdTime: undefined,
|
||||
modifiedTime: undefined,
|
||||
},
|
||||
'test-spreadsheet',
|
||||
[]
|
||||
);
|
||||
|
||||
// Should not contain extra data when fields are undefined
|
||||
expect(JSON.stringify(assetWithNoExtraData.extraInfo)).not.toContain(
|
||||
'label.mime-type'
|
||||
);
|
||||
expect(JSON.stringify(assetWithNoExtraData.extraInfo)).not.toContain(
|
||||
'label.created-time'
|
||||
);
|
||||
expect(JSON.stringify(assetWithNoExtraData.extraInfo)).not.toContain(
|
||||
'label.modified-time'
|
||||
);
|
||||
});
|
||||
|
||||
// Test for Search entity
|
||||
it('Function getDataAssetsHeaderInfo should return data for Search entity', () => {
|
||||
// Search Service
|
||||
@ -652,6 +740,30 @@ describe('Tests for DataAssetsHeaderUtils', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('ExtraInfoLabel', () => {
|
||||
it('should handle React node as value', () => {
|
||||
const nodeValue = (
|
||||
<Tooltip title="Full text value">
|
||||
<Typography.Text ellipsis className="w-full">
|
||||
Truncated text value
|
||||
</Typography.Text>
|
||||
</Tooltip>
|
||||
);
|
||||
|
||||
const { container } = render(
|
||||
<ExtraInfoLabel label="MIME Type" value={nodeValue} />
|
||||
);
|
||||
|
||||
// Check that the component renders without error
|
||||
expect(
|
||||
container.querySelector('.extra-info-container')
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
container.querySelector('.extra-info-label-heading')
|
||||
).toHaveTextContent('MIME Type');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getEntityExtraInfoLength', () => {
|
||||
it('should return 0 for non-React elements', () => {
|
||||
expect(getEntityExtraInfoLength(null)).toBe(0);
|
||||
|
||||
@ -63,6 +63,7 @@ import { PipelineService } from '../generated/entity/services/pipelineService';
|
||||
import { SearchService } from '../generated/entity/services/searchService';
|
||||
import { SecurityService } from '../generated/entity/services/securityService';
|
||||
import { StorageService } from '../generated/entity/services/storageService';
|
||||
import { formatDateTime } from './date-time/DateTimeUtils';
|
||||
import {
|
||||
getBreadcrumbForEntitiesWithServiceOnly,
|
||||
getBreadcrumbForEntityWithParent,
|
||||
@ -103,7 +104,7 @@ export const ExtraInfoLabel = ({
|
||||
return (
|
||||
<div className="d-flex align-start extra-info-container">
|
||||
<Typography.Text
|
||||
className="whitespace-nowrap text-sm d-flex flex-col gap-2"
|
||||
className="whitespace-nowrap text-sm d-flex flex-col gap-2 w-full"
|
||||
data-testid={dataTestId}>
|
||||
{!isEmpty(label) && (
|
||||
<span className="extra-info-label-heading">{label}</span>
|
||||
@ -834,7 +835,13 @@ export const getDataAssetsHeaderInfo = (
|
||||
/>
|
||||
<ExtraInfoLabel
|
||||
label={t('label.mime-type')}
|
||||
value={spreadsheet.mimeType}
|
||||
value={
|
||||
<Tooltip title={spreadsheet.mimeType}>
|
||||
<Typography.Text ellipsis className="w-full">
|
||||
{spreadsheet.mimeType}
|
||||
</Typography.Text>
|
||||
</Tooltip>
|
||||
}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
@ -846,7 +853,7 @@ export const getDataAssetsHeaderInfo = (
|
||||
/>
|
||||
<ExtraInfoLabel
|
||||
label={t('label.created-time')}
|
||||
value={spreadsheet.createdTime}
|
||||
value={formatDateTime(spreadsheet.createdTime)}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
@ -858,7 +865,7 @@ export const getDataAssetsHeaderInfo = (
|
||||
/>
|
||||
<ExtraInfoLabel
|
||||
label={t('label.modified-time')}
|
||||
value={spreadsheet.modifiedTime}
|
||||
value={formatDateTime(spreadsheet.modifiedTime)}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user