diff --git a/apps/desktop/src/components/grid/DataGrid.vue b/apps/desktop/src/components/grid/DataGrid.vue
index 9688a9d899..a73bbf36c4 100644
--- a/apps/desktop/src/components/grid/DataGrid.vue
+++ b/apps/desktop/src/components/grid/DataGrid.vue
@@ -6,6 +6,7 @@ import {
ArrowDown,
ArrowUpDown,
ArrowUpRight,
+ ExternalLink,
Download,
FileUp,
Trash2,
@@ -135,6 +136,7 @@ import {
} from "@/lib/dataGrid/dataGridTranspose";
import { canApplyGridSelectionValue, canDeleteGridRowItem, canEditGridCellDetail, matchesRowStatusFilter, shouldShowQuickEntryDraftRow, type RowStatus, type RowStatusFilter } from "@/lib/dataGrid/gridRowStatus";
import { displayCellValue, firstLineCellDisplayValue, limitDataGridCellDisplay, SQLSERVER_DATA_GRID_CELL_DISPLAY_MAX_LENGTH, type CellValue } from "@/lib/dataGrid/cellValue";
+import { cellExternalUrl } from "@/lib/dataGrid/cellExternalUrl";
import { getApplicablePreviewActions, type PreviewAction } from "@/lib/dataGrid/resultPreviewRegistry";
import "@/lib/dataGrid/geometryMapPreview";
import {
@@ -7889,8 +7891,9 @@ const canvasDetailButtonCell = computed(() => {
const visibleRight = viewportWidth > 0 ? Math.min(viewportWidth, rect.left + rect.width) : rect.left + rect.width;
const canQuickDownload = canQuickDownloadCellValue(target.rowIndex, target.col);
const foreignKey = canvasCellForeignKey(target.rowIndex, target.col);
- if (!cellDetailButtonEnabled.value && !canQuickDownload && !foreignKey) return null;
- const minWidth = canvasDataGridActionOverlayWidth(canQuickDownload, !!foreignKey, cellDetailButtonEnabled.value) + 2;
+ const externalUrl = cellExternalUrl(displayItemAt(target.rowIndex)?.data[target.col]);
+ if (!cellDetailButtonEnabled.value && !canQuickDownload && !foreignKey && !externalUrl) return null;
+ const minWidth = canvasDataGridActionOverlayWidth(canQuickDownload, !!foreignKey, cellDetailButtonEnabled.value, !!externalUrl) + 2;
if (rect.top < 0 || rect.top > viewportHeight - 1 || visibleRight - visibleLeft < minWidth) return null;
return {
rowIndex: target.rowIndex,
@@ -7899,13 +7902,14 @@ const canvasDetailButtonCell = computed(() => {
rect,
canQuickDownload,
foreignKey,
+ externalUrl,
};
});
const canvasDetailButtonStyle = computed(() => {
const cell = canvasDetailButtonCell.value;
if (!cell) return {};
- const actionWidth = canvasDataGridActionOverlayWidth(cell.canQuickDownload, !!cell.foreignKey, cellDetailButtonEnabled.value);
+ const actionWidth = canvasDataGridActionOverlayWidth(cell.canQuickDownload, !!cell.foreignKey, cellDetailButtonEnabled.value, !!cell.externalUrl);
const edgeGap = 6;
return {
left: `${Math.max(rowNumberWidth.value, cell.rect.left + cell.rect.width - actionWidth - edgeGap)}px`,
@@ -7919,7 +7923,7 @@ const canvasRightAlignedActionCell = computed(() => {
return {
rowIndex: cell.rowIndex,
visibleColIdx: cell.visibleColIdx,
- reservedWidth: canvasDataGridActionReservedWidth(cell.canQuickDownload, !!cell.foreignKey, cellDetailButtonEnabled.value),
+ reservedWidth: canvasDataGridActionReservedWidth(cell.canQuickDownload, !!cell.foreignKey, cellDetailButtonEnabled.value, !!cell.externalUrl),
};
});
@@ -9854,6 +9858,25 @@ function canQuickDownloadCellValue(rowIndex: number, columnIndex: number): boole
return canDownloadDetailBinaryValue(cellDetailFor(rowIndex, columnIndex));
}
+function cellExternalUrlFor(rowIndex: number, columnIndex: number): string | null {
+ return cellExternalUrl(displayItemAt(rowIndex)?.data[columnIndex]);
+}
+
+function canOpenCellExternalUrl(rowIndex: number, columnIndex: number): boolean {
+ return cellExternalUrlFor(rowIndex, columnIndex) !== null;
+}
+
+async function openCellExternalUrl(rowIndex: number, columnIndex: number) {
+ const url = cellExternalUrlFor(rowIndex, columnIndex);
+ if (!url) return;
+ try {
+ const { open } = await import("@tauri-apps/plugin-shell");
+ await open(url);
+ } catch {
+ window.open(url, "_blank", "noopener,noreferrer");
+ }
+}
+
function downloadCellBinaryValue(rowIndex: number, columnIndex: number, mode: BinaryCellDownloadMode) {
void downloadDetailBinaryValue(cellDetailFor(rowIndex, columnIndex), mode);
}
@@ -13033,6 +13056,16 @@ function openGridSnapshot() {
+