fix(tdengine): display timezone timestamps and tags correctly
This commit is contained in:
9 files changed
+177
-40
No files matched your search
@@ -5577,6 +5577,7 @@ function cellDetailFor(rowIndex: number, columnIndex: number): DataGridCellDetai
|
||||
canEditCell: canEditCellItem(item, columnIndex),
|
||||
isDraft: !!item.isDraft,
|
||||
}),
|
||||
databaseType: resolvedDatabaseType.value,
|
||||
isValuePreviewTruncated: isLargeValuePreview(item, columnIndex),
|
||||
});
|
||||
}
|
||||
@@ -5706,7 +5707,7 @@ const activeCellDetailTabs = computed(() => {
|
||||
const activeBinaryHexBytes = computed(() => {
|
||||
if (activeCellDetailTab.value !== "hexViewer") return null;
|
||||
const detail = activeCellDetail.value;
|
||||
return detail ? parseBinaryCellBytes(detail.value, detail.type) : null;
|
||||
return detail ? parseBinaryCellBytes(detail.value, detail.type, resolvedDatabaseType.value) : null;
|
||||
});
|
||||
|
||||
const activeBinaryHexRows = computed(() => (activeBinaryHexBytes.value ? buildBinaryHexViewRows(activeBinaryHexBytes.value) : []));
|
||||
@@ -6326,7 +6327,7 @@ function formatCell(value: CellValue, columnIndex?: number, originalBytes?: numb
|
||||
columnInfo: displayColumnInfo,
|
||||
});
|
||||
if (arrayDisplay !== undefined) return arrayDisplay;
|
||||
const binaryDisplay = formatter ? null : binaryCellDisplayText(value, columnIndex === undefined ? undefined : allColumnTypes.value[columnIndex], originalBytes);
|
||||
const binaryDisplay = formatter ? null : binaryCellDisplayText(value, columnIndex === undefined ? undefined : allColumnTypes.value[columnIndex], originalBytes, resolvedDatabaseType.value);
|
||||
if (binaryDisplay !== null) return binaryDisplay;
|
||||
const s = applyColumnFormatter(value, formatter);
|
||||
return limitDisplay ? limitDataGridCellDisplay(s, resolvedDatabaseType.value === "sqlserver" ? SQLSERVER_DATA_GRID_CELL_DISPLAY_MAX_LENGTH : undefined) : s;
|
||||
@@ -8922,7 +8923,7 @@ function copyDetailColumnName() {
|
||||
function canDownloadDetailBinaryValue(detail: DataGridCellDetail | null): boolean {
|
||||
if (!detail) return false;
|
||||
const item = getRowItem(detail.rowId);
|
||||
return (isLargeValuePreview(item, detail.colIndex) && isBinaryCellColumnType(detail.type)) || canDownloadBinaryCellValue(detail.value, detail.type);
|
||||
return (resolvedDatabaseType.value !== "tdengine" && isLargeValuePreview(item, detail.colIndex) && isBinaryCellColumnType(detail.type)) || canDownloadBinaryCellValue(detail.value, detail.type, resolvedDatabaseType.value);
|
||||
}
|
||||
|
||||
function canImportDetailBinaryValue(detail: DataGridCellDetail | null): boolean {
|
||||
@@ -8972,7 +8973,7 @@ async function downloadDetailBinaryValue(detail: DataGridCellDetail | null, mode
|
||||
if (!(await hydrateLargeValueCell(detail.rowId, detail.colIndex))) return;
|
||||
const resolvedDetail = cellDetailFor(detail.rowNumber - 1, detail.colIndex);
|
||||
if (!resolvedDetail) return;
|
||||
const payload = binaryCellDownloadPayload(resolvedDetail.value, mode, resolvedDetail.type);
|
||||
const payload = binaryCellDownloadPayload(resolvedDetail.value, mode, resolvedDetail.type, resolvedDatabaseType.value);
|
||||
const fileName = binaryCellDownloadFileName({
|
||||
column: resolvedDetail.column,
|
||||
rowNumber: resolvedDetail.rowNumber,
|
||||
|
||||
@@ -159,7 +159,7 @@ function bytesFromBufferLikeObject(value: unknown): Uint8Array | null {
|
||||
return bytesFromByteArray(data);
|
||||
}
|
||||
|
||||
export function parseBinaryCellBytes(value: unknown, columnType?: string): Uint8Array | null {
|
||||
export function parseBinaryCellBytes(value: unknown, columnType?: string, databaseType?: DatabaseType): Uint8Array | null {
|
||||
if (typeof value === "string") {
|
||||
const prefixed = parseBinaryCellHexValue(value);
|
||||
if (prefixed) return prefixed;
|
||||
@@ -169,7 +169,7 @@ export function parseBinaryCellBytes(value: unknown, columnType?: string): Uint8
|
||||
return bytesFromHex(trimmed.replace(/\\x/gi, ""));
|
||||
}
|
||||
|
||||
if (isBinaryCellColumnType(columnType) && BARE_HEX_RE.test(trimmed)) {
|
||||
if (databaseType !== "tdengine" && isBinaryCellColumnType(columnType) && BARE_HEX_RE.test(trimmed)) {
|
||||
return bytesFromHex(trimmed);
|
||||
}
|
||||
}
|
||||
@@ -189,16 +189,16 @@ export function canImportBinaryCellFile(databaseType?: DatabaseType, columnType?
|
||||
return false;
|
||||
}
|
||||
|
||||
export function canDownloadBinaryCellValue(value: unknown, columnType?: string): boolean {
|
||||
return !!parseBinaryCellBytes(value, columnType);
|
||||
export function canDownloadBinaryCellValue(value: unknown, columnType?: string, databaseType?: DatabaseType): boolean {
|
||||
return !!parseBinaryCellBytes(value, columnType, databaseType);
|
||||
}
|
||||
|
||||
export function binaryCellDisplayText(value: unknown, columnType?: string, originalBytes?: number): string | null {
|
||||
export function binaryCellDisplayText(value: unknown, columnType?: string, originalBytes?: number, databaseType?: DatabaseType): string | null {
|
||||
if (typeof value === "string" && isBinaryCellColumnType(columnType) && TRUNCATED_HEX_VALUE_RE.test(value.trim())) {
|
||||
const size = originalBytes === undefined ? "..." : formatBinaryCellByteSize(originalBytes);
|
||||
return `${binaryCellDisplayLabel(columnType)} [${size}]`;
|
||||
}
|
||||
const bytes = parseBinaryCellBytes(value, columnType);
|
||||
const bytes = parseBinaryCellBytes(value, columnType, databaseType);
|
||||
if (!bytes || !isBinaryCellColumnType(columnType)) return null;
|
||||
if (BINARY_STRING_TYPE_RE.test((columnType ?? "").trim())) {
|
||||
const previewBytes = FIXED_BINARY_TYPE_RE.test((columnType ?? "").trim()) ? trimTrailingNullBytes(bytes) : bytes;
|
||||
@@ -245,8 +245,8 @@ export function formatBinaryCellByteSize(bytes: number): string {
|
||||
return `${(bytes / (1024 * 1024)).toFixed(bytes < 10 * 1024 * 1024 ? 1 : 0)} MB`;
|
||||
}
|
||||
|
||||
export function binaryCellDownloadPayload(value: unknown, mode: BinaryCellDownloadMode, columnType?: string): BinaryCellDownloadPayload {
|
||||
const bytes = parseBinaryCellBytes(value, columnType);
|
||||
export function binaryCellDownloadPayload(value: unknown, mode: BinaryCellDownloadMode, columnType?: string, databaseType?: DatabaseType): BinaryCellDownloadPayload {
|
||||
const bytes = parseBinaryCellBytes(value, columnType, databaseType);
|
||||
if (!bytes) {
|
||||
throw new Error("Cell value is not a downloadable binary value.");
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { CellValue } from "@/lib/dataGrid/cellValue";
|
||||
import { isBinaryCellColumnType, parseBinaryCellBytes } from "@/lib/dataGrid/binaryCellDownload";
|
||||
import type { DatabaseType } from "@/types/database";
|
||||
|
||||
const IMAGE_PATH_RE = /\.(?:png|jpe?g|webp|gif|avif|bmp|svg)$/i;
|
||||
const SAFE_DATA_IMAGE_RE = /^data:image\/(?:png|jpe?g|webp|gif|avif|bmp);base64,[a-z0-9+/=\s]+$/i;
|
||||
@@ -14,10 +15,11 @@ function isLocalHttpHost(hostname: string): boolean {
|
||||
|
||||
export interface CellImagePreviewOptions {
|
||||
binary?: boolean;
|
||||
databaseType?: DatabaseType;
|
||||
}
|
||||
|
||||
export function cellImagePreviewUrl(value: CellValue | unknown, columnType?: string, options: CellImagePreviewOptions = {}): string | null {
|
||||
const binaryPreviewUrl = options.binary === false ? null : binaryImagePreviewUrl(value, columnType);
|
||||
const binaryPreviewUrl = options.binary === false ? null : binaryImagePreviewUrl(value, columnType, options.databaseType);
|
||||
if (binaryPreviewUrl) return binaryPreviewUrl;
|
||||
|
||||
if (typeof value !== "string") return null;
|
||||
@@ -38,16 +40,16 @@ export function cellImagePreviewUrl(value: CellValue | unknown, columnType?: str
|
||||
return text;
|
||||
}
|
||||
|
||||
function binaryImagePreviewUrl(value: unknown, columnType?: string): string | null {
|
||||
if (estimatedBinaryByteLength(value, columnType) > MAX_BINARY_IMAGE_PREVIEW_BYTES) return null;
|
||||
const bytes = parseBinaryCellBytes(value, columnType);
|
||||
function binaryImagePreviewUrl(value: unknown, columnType?: string, databaseType?: DatabaseType): string | null {
|
||||
if (estimatedBinaryByteLength(value, columnType, databaseType) > MAX_BINARY_IMAGE_PREVIEW_BYTES) return null;
|
||||
const bytes = parseBinaryCellBytes(value, columnType, databaseType);
|
||||
if (!bytes || bytes.length > MAX_BINARY_IMAGE_PREVIEW_BYTES) return null;
|
||||
const mimeType = detectImageMimeType(bytes);
|
||||
if (!mimeType) return null;
|
||||
return `data:${mimeType};base64,${bytesToBase64(bytes)}`;
|
||||
}
|
||||
|
||||
function estimatedBinaryByteLength(value: unknown, columnType?: string): number {
|
||||
function estimatedBinaryByteLength(value: unknown, columnType?: string, databaseType?: DatabaseType): number {
|
||||
if (Array.isArray(value)) return value.length;
|
||||
if (value && typeof value === "object" && Array.isArray((value as { data?: unknown }).data)) {
|
||||
return (value as { data: unknown[] }).data.length;
|
||||
@@ -58,7 +60,9 @@ function estimatedBinaryByteLength(value: unknown, columnType?: string): number
|
||||
const prefixed = trimmed.match(HEX_PREFIX_RE);
|
||||
if (prefixed) return prefixed[1].replace(/\s+/g, "").length / 2;
|
||||
if (HEX_ESCAPE_RE.test(trimmed)) return trimmed.replace(/\s+/g, "").replace(/\\x/gi, "").length / 2;
|
||||
if (isBinaryCellColumnType(columnType) && BARE_HEX_RE.test(trimmed)) return trimmed.replace(/\s+/g, "").length / 2;
|
||||
if (databaseType !== "tdengine" && isBinaryCellColumnType(columnType) && BARE_HEX_RE.test(trimmed)) {
|
||||
return trimmed.replace(/\s+/g, "").length / 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { cellImagePreviewUrl } from "@/lib/dataGrid/cellImageUrl";
|
||||
import { displayCellValue, type CellValue } from "@/lib/dataGrid/cellValue";
|
||||
import { formatJsonText } from "@/lib/dataGrid/cellDetailPresentation";
|
||||
import type { DatabaseType } from "@/types/database";
|
||||
|
||||
export const CELL_DETAIL_VALUE_PREVIEW_MAX_LENGTH = 12_000;
|
||||
|
||||
@@ -48,6 +49,7 @@ export interface BuildDataGridCellDetailOptions {
|
||||
commentByColumn?: ReadonlyMap<string, string>;
|
||||
displayValue: (value: CellValue, columnIndex: number) => string;
|
||||
isEditable: boolean;
|
||||
databaseType?: DatabaseType;
|
||||
includeBinaryImagePreview?: boolean;
|
||||
isValuePreviewTruncated?: boolean;
|
||||
}
|
||||
@@ -109,7 +111,10 @@ export function buildDataGridCellDetail(options: BuildDataGridCellDetailOptions)
|
||||
displayValue,
|
||||
displayValuePreview,
|
||||
isValuePreviewTruncated: options.isValuePreviewTruncated === true || rawValuePreview.length < rawValue.length || displayValuePreview.length < displayValue.length,
|
||||
imagePreviewUrl: cellImagePreviewUrl(value, type, { binary: options.includeBinaryImagePreview !== false }),
|
||||
imagePreviewUrl: cellImagePreviewUrl(value, type, {
|
||||
binary: options.includeBinaryImagePreview !== false,
|
||||
databaseType: options.databaseType,
|
||||
}),
|
||||
length: value === null ? 0 : String(value).length,
|
||||
formattedJson,
|
||||
isEditable: options.isEditable,
|
||||
|
||||
Reference in new issue
Block a user