From d9e3fb2b8ea56527acc9d6206884a79b917cb688 Mon Sep 17 00:00:00 2001 From: Chris Lu Date: Sat, 7 Feb 2026 23:59:49 -0800 Subject: [PATCH] Add Iceberg table details view --- weed/admin/dash/s3tables_management.go | 279 ++++++++ weed/admin/dash/types.go | 53 ++ weed/admin/handlers/admin_handlers.go | 28 + weed/admin/static/js/s3tables.js | 198 ++++++ weed/admin/view/app/file_browser_templ.go | 178 ++--- .../view/app/iceberg_table_details.templ | 376 +++++++++++ .../view/app/iceberg_table_details_templ.go | 618 ++++++++++++++++++ 7 files changed, 1641 insertions(+), 89 deletions(-) create mode 100644 weed/admin/view/app/iceberg_table_details.templ create mode 100644 weed/admin/view/app/iceberg_table_details_templ.go diff --git a/weed/admin/dash/s3tables_management.go b/weed/admin/dash/s3tables_management.go index a77a8201c..2903a6ebe 100644 --- a/weed/admin/dash/s3tables_management.go +++ b/weed/admin/dash/s3tables_management.go @@ -7,6 +7,8 @@ import ( "fmt" "io" "net/http" + "sort" + "strconv" "strings" "time" @@ -218,6 +220,7 @@ func (s *AdminServer) GetIcebergNamespacesData(ctx context.Context, catalogName, return IcebergNamespacesData{ CatalogName: catalogName, + BucketARN: bucketArn, Namespaces: namespaces, TotalNamespaces: len(namespaces), LastUpdated: time.Now(), @@ -242,12 +245,288 @@ func (s *AdminServer) GetIcebergTablesData(ctx context.Context, catalogName, buc return IcebergTablesData{ CatalogName: catalogName, NamespaceName: namespace, + BucketARN: bucketArn, Tables: tables, TotalTables: len(tables), LastUpdated: time.Now(), }, nil } +// GetIcebergTableDetailsData returns Iceberg table metadata and snapshot information. +func (s *AdminServer) GetIcebergTableDetailsData(ctx context.Context, catalogName, bucketArn, namespace, tableName string) (IcebergTableDetailsData, error) { + var resp s3tables.GetTableResponse + req := &s3tables.GetTableRequest{ + TableBucketARN: bucketArn, + Namespace: []string{namespace}, + Name: tableName, + } + if err := s.executeS3TablesOperation(ctx, "GetTable", req, &resp); err != nil { + return IcebergTableDetailsData{}, err + } + + details := IcebergTableDetailsData{ + CatalogName: catalogName, + NamespaceName: namespace, + TableName: resp.Name, + BucketARN: bucketArn, + TableARN: resp.TableARN, + Format: resp.Format, + CreatedAt: resp.CreatedAt, + ModifiedAt: resp.ModifiedAt, + MetadataLocation: resp.MetadataLocation, + } + + applyIcebergMetadata(resp.Metadata, &details) + return details, nil +} + +type icebergFullMetadata struct { + FormatVersion int `json:"format-version"` + TableUUID string `json:"table-uuid"` + Location string `json:"location"` + LastUpdatedMs int64 `json:"last-updated-ms"` + Schemas []icebergSchema `json:"schemas"` + Schema *icebergSchema `json:"schema"` + CurrentSchemaID int `json:"current-schema-id"` + PartitionSpecs []icebergPartitionSpec `json:"partition-specs"` + PartitionSpec *icebergPartitionSpec `json:"partition-spec"` + DefaultSpecID int `json:"default-spec-id"` + Properties map[string]string `json:"properties"` + Snapshots []icebergSnapshot `json:"snapshots"` + CurrentSnapshotID int64 `json:"current-snapshot-id"` +} + +type icebergSchema struct { + SchemaID int `json:"schema-id"` + Fields []icebergSchemaField `json:"fields"` +} + +type icebergSchemaField struct { + ID int `json:"id"` + Name string `json:"name"` + Type string `json:"type"` + Required bool `json:"required"` +} + +type icebergPartitionSpec struct { + SpecID int `json:"spec-id"` + Fields []icebergPartitionField `json:"fields"` +} + +type icebergPartitionField struct { + SourceID int `json:"source-id"` + FieldID int `json:"field-id"` + Name string `json:"name"` + Transform string `json:"transform"` +} + +type icebergSnapshot struct { + SnapshotID int64 `json:"snapshot-id"` + TimestampMs int64 `json:"timestamp-ms"` + ManifestList string `json:"manifest-list"` + Summary map[string]string `json:"summary"` +} + +func applyIcebergMetadata(metadata *s3tables.TableMetadata, details *IcebergTableDetailsData) { + if details == nil || metadata == nil { + return + } + if len(metadata.FullMetadata) == 0 { + details.SchemaFields = schemaFieldsFromIceberg(metadata.Iceberg) + return + } + + var full icebergFullMetadata + if err := json.Unmarshal(metadata.FullMetadata, &full); err != nil { + glog.V(1).Infof("iceberg metadata parse failed: %v", err) + details.MetadataError = fmt.Sprintf("Failed to parse Iceberg metadata: %v", err) + details.SchemaFields = schemaFieldsFromIceberg(metadata.Iceberg) + return + } + + details.TableLocation = full.Location + details.SchemaFields = schemaFieldsFromFullMetadata(full, metadata.Iceberg) + details.PartitionFields = partitionFieldsFromFullMetadata(full) + details.Properties = propertiesFromFullMetadata(full.Properties) + details.Snapshots = snapshotsFromFullMetadata(full.Snapshots) + details.SnapshotCount = len(full.Snapshots) + details.HasSnapshotCount = true + if metricsSnapshot := selectSnapshotForMetrics(full); metricsSnapshot != nil { + if value, ok := parseSummaryInt(metricsSnapshot.Summary, "total-data-files", "total-data-file-count", "total-files", "total-file-count"); ok { + details.DataFileCount = value + details.HasDataFileCount = true + } + if value, ok := parseSummaryInt(metricsSnapshot.Summary, "total-files-size", "total-data-files-size", "total-file-size", "total-data-file-size", "total-data-size", "total-size"); ok { + details.TotalSizeBytes = value + details.HasTotalSize = true + } + } +} + +func schemaFieldsFromFullMetadata(full icebergFullMetadata, fallback *s3tables.IcebergMetadata) []IcebergSchemaFieldInfo { + if schema := selectSchema(full); schema != nil { + fields := make([]IcebergSchemaFieldInfo, 0, len(schema.Fields)) + for _, field := range schema.Fields { + fields = append(fields, IcebergSchemaFieldInfo{ + ID: field.ID, + Name: field.Name, + Type: field.Type, + Required: field.Required, + }) + } + return fields + } + return schemaFieldsFromIceberg(fallback) +} + +func schemaFieldsFromIceberg(metadata *s3tables.IcebergMetadata) []IcebergSchemaFieldInfo { + if metadata == nil { + return nil + } + fields := make([]IcebergSchemaFieldInfo, 0, len(metadata.Schema.Fields)) + for _, field := range metadata.Schema.Fields { + fields = append(fields, IcebergSchemaFieldInfo{ + Name: field.Name, + Type: field.Type, + Required: field.Required, + }) + } + return fields +} + +func selectSchema(full icebergFullMetadata) *icebergSchema { + if len(full.Schemas) == 0 && full.Schema == nil { + return nil + } + if len(full.Schemas) == 0 { + return full.Schema + } + if full.CurrentSchemaID != 0 { + for i := range full.Schemas { + if full.Schemas[i].SchemaID == full.CurrentSchemaID { + return &full.Schemas[i] + } + } + } + return &full.Schemas[0] +} + +func partitionFieldsFromFullMetadata(full icebergFullMetadata) []IcebergPartitionFieldInfo { + var spec *icebergPartitionSpec + if len(full.PartitionSpecs) == 0 && full.PartitionSpec == nil { + return nil + } + if len(full.PartitionSpecs) == 0 { + spec = full.PartitionSpec + } else { + if full.DefaultSpecID != 0 { + for i := range full.PartitionSpecs { + if full.PartitionSpecs[i].SpecID == full.DefaultSpecID { + spec = &full.PartitionSpecs[i] + break + } + } + } + if spec == nil { + spec = &full.PartitionSpecs[0] + } + } + if spec == nil { + return nil + } + fields := make([]IcebergPartitionFieldInfo, 0, len(spec.Fields)) + for _, field := range spec.Fields { + fields = append(fields, IcebergPartitionFieldInfo{ + Name: field.Name, + Transform: field.Transform, + SourceID: field.SourceID, + FieldID: field.FieldID, + }) + } + return fields +} + +func propertiesFromFullMetadata(properties map[string]string) []IcebergPropertyInfo { + if len(properties) == 0 { + return nil + } + keys := make([]string, 0, len(properties)) + for key := range properties { + keys = append(keys, key) + } + sort.Strings(keys) + entries := make([]IcebergPropertyInfo, 0, len(keys)) + for _, key := range keys { + entries = append(entries, IcebergPropertyInfo{Key: key, Value: properties[key]}) + } + return entries +} + +func snapshotsFromFullMetadata(snapshots []icebergSnapshot) []IcebergSnapshotInfo { + if len(snapshots) == 0 { + return nil + } + sort.Slice(snapshots, func(i, j int) bool { + return snapshots[i].TimestampMs > snapshots[j].TimestampMs + }) + info := make([]IcebergSnapshotInfo, 0, len(snapshots)) + for _, snapshot := range snapshots { + operation := "" + if snapshot.Summary != nil { + operation = snapshot.Summary["operation"] + } + timestamp := time.Time{} + if snapshot.TimestampMs > 0 { + timestamp = time.Unix(0, snapshot.TimestampMs*int64(time.Millisecond)) + } + info = append(info, IcebergSnapshotInfo{ + SnapshotID: snapshot.SnapshotID, + Timestamp: timestamp, + Operation: operation, + ManifestList: snapshot.ManifestList, + }) + } + return info +} + +func selectSnapshotForMetrics(full icebergFullMetadata) *icebergSnapshot { + if len(full.Snapshots) == 0 { + return nil + } + if full.CurrentSnapshotID != 0 { + for i := range full.Snapshots { + if full.Snapshots[i].SnapshotID == full.CurrentSnapshotID { + return &full.Snapshots[i] + } + } + } + latest := full.Snapshots[0] + for _, snapshot := range full.Snapshots[1:] { + if snapshot.TimestampMs > latest.TimestampMs { + latest = snapshot + } + } + return &latest +} + +func parseSummaryInt(summary map[string]string, keys ...string) (int64, bool) { + if len(summary) == 0 { + return 0, false + } + for _, key := range keys { + value, ok := summary[key] + if !ok || value == "" { + continue + } + parsed, err := strconv.ParseInt(value, 10, 64) + if err != nil { + continue + } + return parsed, true + } + return 0, false +} + // API handlers func (s *AdminServer) ListS3TablesBucketsAPI(c *gin.Context) { diff --git a/weed/admin/dash/types.go b/weed/admin/dash/types.go index 49483d5f5..9f230db40 100644 --- a/weed/admin/dash/types.go +++ b/weed/admin/dash/types.go @@ -621,6 +621,7 @@ type IcebergNamespaceInfo struct { type IcebergNamespacesData struct { Username string `json:"username"` CatalogName string `json:"catalog_name"` + BucketARN string `json:"bucket_arn"` Namespaces []IcebergNamespaceInfo `json:"namespaces"` TotalNamespaces int `json:"total_namespaces"` LastUpdated time.Time `json:"last_updated"` @@ -635,7 +636,59 @@ type IcebergTablesData struct { Username string `json:"username"` CatalogName string `json:"catalog_name"` NamespaceName string `json:"namespace_name"` + BucketARN string `json:"bucket_arn"` Tables []IcebergTableInfo `json:"tables"` TotalTables int `json:"total_tables"` LastUpdated time.Time `json:"last_updated"` } + +type IcebergSchemaFieldInfo struct { + ID int `json:"id"` + Name string `json:"name"` + Type string `json:"type"` + Required bool `json:"required"` +} + +type IcebergPartitionFieldInfo struct { + Name string `json:"name"` + Transform string `json:"transform"` + SourceID int `json:"source_id"` + FieldID int `json:"field_id"` +} + +type IcebergPropertyInfo struct { + Key string `json:"key"` + Value string `json:"value"` +} + +type IcebergSnapshotInfo struct { + SnapshotID int64 `json:"snapshot_id"` + Timestamp time.Time `json:"timestamp"` + Operation string `json:"operation"` + ManifestList string `json:"manifest_list"` +} + +type IcebergTableDetailsData struct { + Username string `json:"username"` + CatalogName string `json:"catalog_name"` + NamespaceName string `json:"namespace_name"` + TableName string `json:"table_name"` + BucketARN string `json:"bucket_arn"` + TableARN string `json:"table_arn"` + Format string `json:"format"` + CreatedAt time.Time `json:"created_at"` + ModifiedAt time.Time `json:"modified_at"` + MetadataLocation string `json:"metadata_location"` + TableLocation string `json:"table_location"` + SchemaFields []IcebergSchemaFieldInfo `json:"schema_fields"` + PartitionFields []IcebergPartitionFieldInfo `json:"partition_fields"` + Properties []IcebergPropertyInfo `json:"properties"` + Snapshots []IcebergSnapshotInfo `json:"snapshots"` + SnapshotCount int `json:"snapshot_count"` + HasSnapshotCount bool `json:"has_snapshot_count"` + DataFileCount int64 `json:"data_file_count"` + HasDataFileCount bool `json:"has_data_file_count"` + TotalSizeBytes int64 `json:"total_size_bytes"` + HasTotalSize bool `json:"has_total_size"` + MetadataError string `json:"metadata_error,omitempty"` +} diff --git a/weed/admin/handlers/admin_handlers.go b/weed/admin/handlers/admin_handlers.go index 564a509f4..79d69bcef 100644 --- a/weed/admin/handlers/admin_handlers.go +++ b/weed/admin/handlers/admin_handlers.go @@ -94,6 +94,7 @@ func (h *AdminHandlers) SetupRoutes(r *gin.Engine, authRequired bool, adminUser, protected.GET("/object-store/iceberg", h.ShowIcebergCatalog) protected.GET("/object-store/iceberg/:catalog/namespaces", h.ShowIcebergNamespaces) protected.GET("/object-store/iceberg/:catalog/namespaces/:namespace/tables", h.ShowIcebergTables) + protected.GET("/object-store/iceberg/:catalog/namespaces/:namespace/tables/:table", h.ShowIcebergTableDetails) // File browser routes protected.GET("/files", h.fileBrowserHandlers.ShowFileBrowser) @@ -265,6 +266,7 @@ func (h *AdminHandlers) SetupRoutes(r *gin.Engine, authRequired bool, adminUser, r.GET("/object-store/iceberg", h.ShowIcebergCatalog) r.GET("/object-store/iceberg/:catalog/namespaces", h.ShowIcebergNamespaces) r.GET("/object-store/iceberg/:catalog/namespaces/:namespace/tables", h.ShowIcebergTables) + r.GET("/object-store/iceberg/:catalog/namespaces/:namespace/tables/:table", h.ShowIcebergTableDetails) // File browser routes r.GET("/files", h.fileBrowserHandlers.ShowFileBrowser) @@ -609,6 +611,32 @@ func (h *AdminHandlers) ShowIcebergTables(c *gin.Context) { } } +// ShowIcebergTableDetails renders the table metadata and snapshot details view. +func (h *AdminHandlers) ShowIcebergTableDetails(c *gin.Context) { + catalogName := c.Param("catalog") + namespace := c.Param("namespace") + tableName := c.Param("table") + arn, err := buildS3TablesBucketArn(catalogName) + if err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + + data, err := h.adminServer.GetIcebergTableDetailsData(c.Request.Context(), catalogName, arn, namespace, tableName) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get Iceberg table details: " + err.Error()}) + return + } + data.Username = h.getUsername(c) + + c.Header("Content-Type", "text/html") + component := app.IcebergTableDetails(data) + layoutComponent := layout.Layout(c, component) + if err := layoutComponent.Render(c.Request.Context(), c.Writer); err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to render template: " + err.Error()}) + } +} + // ShowBucketDetails returns detailed information about a specific bucket func (h *AdminHandlers) ShowBucketDetails(c *gin.Context) { bucketName := c.Param("bucket") diff --git a/weed/admin/static/js/s3tables.js b/weed/admin/static/js/s3tables.js index 4c484bce5..148b1e365 100644 --- a/weed/admin/static/js/s3tables.js +++ b/weed/admin/static/js/s3tables.js @@ -9,6 +9,7 @@ let s3tablesNamespaceDeleteModal = null; let s3tablesTableDeleteModal = null; let s3tablesTablePolicyModal = null; let s3tablesTagsModal = null; +let icebergTableDeleteModal = null; /** * Initialize S3 Tables Buckets Page @@ -261,6 +262,173 @@ function initS3TablesTables() { } } +/** + * Initialize Iceberg Namespaces Page + */ +function initIcebergNamespaces() { + const container = document.getElementById('iceberg-namespaces-content'); + if (!container) return; + const bucketArn = container.dataset.bucketArn || ''; + const catalogName = container.dataset.catalogName || ''; + + const createForm = document.getElementById('createIcebergNamespaceForm'); + if (createForm) { + createForm.addEventListener('submit', async function (e) { + e.preventDefault(); + const name = document.getElementById('icebergNamespaceName').value.trim(); + if (!name) { + alert('Namespace name is required'); + return; + } + try { + const response = await fetch('/api/s3tables/namespaces', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ bucket_arn: bucketArn, name: name }) + }); + const data = await response.json(); + if (!response.ok) { + alert(data.error || 'Failed to create namespace'); + return; + } + alert('Namespace created'); + location.reload(); + } catch (error) { + alert('Failed to create namespace: ' + error.message); + } + }); + } + + initIcebergNamespaceTree(container, bucketArn, catalogName); +} + +function initIcebergNamespaceTree(container, bucketArn, catalogName) { + const nodes = container.querySelectorAll('.iceberg-namespace-collapse'); + nodes.forEach(node => { + node.addEventListener('show.bs.collapse', async function () { + if (node.dataset.loaded === 'true') return; + node.dataset.loaded = 'true'; + node.innerHTML = '
Loading...
'; + await loadIcebergNamespaceTables(node, bucketArn, catalogName); + }); + }); +} + +async function loadIcebergNamespaceTables(node, bucketArn, catalogName) { + const namespace = node.dataset.namespace || ''; + if (!bucketArn || !namespace) { + node.innerHTML = '
No namespace data available.
'; + return; + } + try { + const query = new URLSearchParams({ bucket: bucketArn, namespace: namespace }); + const response = await fetch(`/api/s3tables/tables?${query.toString()}`); + const data = await response.json(); + if (!response.ok) { + node.innerHTML = `
${data.error || 'Failed to load tables'}
`; + return; + } + const tables = data.tables || []; + if (tables.length === 0) { + node.innerHTML = '
No tables found.
'; + return; + } + const list = document.createElement('ul'); + list.className = 'list-group list-group-flush ms-3'; + tables.forEach(table => { + const item = document.createElement('li'); + item.className = 'list-group-item py-1'; + const link = document.createElement('a'); + link.className = 'text-decoration-none'; + link.href = `/object-store/iceberg/${encodeURIComponent(catalogName)}/namespaces/${encodeURIComponent(namespace)}/tables/${encodeURIComponent(table.name)}`; + link.innerHTML = `${table.name}`; + item.appendChild(link); + list.appendChild(item); + }); + node.innerHTML = ''; + node.appendChild(list); + } catch (error) { + node.innerHTML = `
${error.message}
`; + } +} + +/** + * Initialize Iceberg Tables Page + */ +function initIcebergTables() { + const container = document.getElementById('iceberg-tables-content'); + if (!container) return; + const bucketArn = container.dataset.bucketArn || ''; + const namespace = container.dataset.namespace || ''; + + initIcebergDeleteModal(); + + const createForm = document.getElementById('createIcebergTableForm'); + if (createForm) { + createForm.addEventListener('submit', async function (e) { + e.preventDefault(); + const name = document.getElementById('icebergTableName').value.trim(); + const format = document.getElementById('icebergTableFormat').value; + const metadataText = document.getElementById('icebergTableMetadata').value.trim(); + const tagsInput = document.getElementById('icebergTableTags').value.trim(); + const tags = parseTagsInput(tagsInput); + if (tags === null) return; + let metadata = null; + if (metadataText) { + try { + metadata = JSON.parse(metadataText); + } catch (error) { + alert('Invalid metadata JSON'); + return; + } + } + const payload = { bucket_arn: bucketArn, namespace: namespace, name: name, format: format, tags: tags }; + if (metadata) { + payload.metadata = metadata; + } + try { + const response = await fetch('/api/s3tables/tables', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(payload) + }); + const data = await response.json(); + if (!response.ok) { + alert(data.error || 'Failed to create table'); + return; + } + alert('Table created'); + location.reload(); + } catch (error) { + alert('Failed to create table: ' + error.message); + } + }); + } +} + +/** + * Initialize Iceberg Table Details Page + */ +function initIcebergTableDetails() { + initIcebergDeleteModal(); +} + +function initIcebergDeleteModal() { + const modalEl = document.getElementById('deleteIcebergTableModal'); + if (!modalEl) return; + icebergTableDeleteModal = new bootstrap.Modal(modalEl); + document.querySelectorAll('.iceberg-delete-table-btn').forEach(button => { + button.addEventListener('click', function () { + modalEl.dataset.bucketArn = this.dataset.bucketArn || ''; + modalEl.dataset.namespace = this.dataset.namespace || ''; + modalEl.dataset.tableName = this.dataset.tableName || ''; + document.getElementById('deleteIcebergTableName').textContent = this.dataset.tableName || ''; + document.getElementById('deleteIcebergTableVersion').value = ''; + icebergTableDeleteModal.show(); + }); + }); +} + // Global scope functions used by onclick handlers async function deleteS3TablesBucket() { @@ -340,6 +508,36 @@ async function deleteS3TablesTable() { } } +async function deleteIcebergTable() { + const modalEl = document.getElementById('deleteIcebergTableModal'); + if (!modalEl) return; + const bucketArn = modalEl.dataset.bucketArn || ''; + const namespace = modalEl.dataset.namespace || ''; + const tableName = modalEl.dataset.tableName || ''; + const versionToken = document.getElementById('deleteIcebergTableVersion').value.trim(); + if (!bucketArn || !namespace || !tableName) return; + const query = new URLSearchParams({ + bucket: bucketArn, + namespace: namespace, + name: tableName + }); + if (versionToken) { + query.set('version', versionToken); + } + try { + const response = await fetch(`/api/s3tables/tables?${query.toString()}`, { method: 'DELETE' }); + const data = await response.json(); + if (!response.ok) { + alert(data.error || 'Failed to drop table'); + return; + } + alert('Table dropped'); + location.reload(); + } catch (error) { + alert('Failed to drop table: ' + error.message); + } +} + async function loadS3TablesTablePolicy(bucketArn, namespace, name) { document.getElementById('s3tablesTablePolicyText').value = ''; if (!bucketArn || !namespace || !name) return; diff --git a/weed/admin/view/app/file_browser_templ.go b/weed/admin/view/app/file_browser_templ.go index 230471fc1..8a7be7142 100644 --- a/weed/admin/view/app/file_browser_templ.go +++ b/weed/admin/view/app/file_browser_templ.go @@ -58,7 +58,7 @@ func FileBrowser(data dash.FileBrowserData) templ.Component { var templ_7745c5c3_Var2 string templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(data.TableBucketName) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/file_browser.templ`, Line: 18, Col: 72} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/file_browser.templ`, Line: 18, Col: 71} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2)) if templ_7745c5c3_Err != nil { @@ -72,7 +72,7 @@ func FileBrowser(data dash.FileBrowserData) templ.Component { var templ_7745c5c3_Var3 string templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(data.BucketName) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/file_browser.templ`, Line: 20, Col: 63} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/file_browser.templ`, Line: 20, Col: 62} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) if templ_7745c5c3_Err != nil { @@ -189,38 +189,38 @@ func FileBrowser(data dash.FileBrowserData) templ.Component { return templ_7745c5c3_Err } } else { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "\" class=\"text-decoration-none text-primary\">") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var9 string templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(filepath.Base(data.CurrentPath)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/file_browser.templ`, Line: 94, Col: 154} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/file_browser.templ`, Line: 89, Col: 154} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -228,7 +228,7 @@ func FileBrowser(data dash.FileBrowserData) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, ">200
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if data.HasNextPage { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, "Next ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, "\" class=\"btn btn-outline-primary\" title=\"Next page\">Next ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } else { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 36, " ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 35, " ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } if data.ParentPath != data.CurrentPath { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 37, " Up") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 37, "\" class=\"btn btn-outline-secondary\" title=\"Go up one directory\"> Up") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 39, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 38, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if len(data.Entries) > 0 { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 40, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 39, "
NameSizeTypeModifiedPermissionsActions
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } for _, entry := range data.Entries { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 41, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 63, "\">") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 65, "
NameSizeTypeModifiedPermissionsActions
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 41, "\">
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if entry.IsDirectory { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 43, " ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 43, "\" class=\"text-decoration-none\">") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var15 string templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(entry.Name) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/file_browser.templ`, Line: 155, Col: 25} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/file_browser.templ`, Line: 150, Col: 25} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 45, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 44, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -388,7 +388,7 @@ func FileBrowser(data dash.FileBrowserData) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 46, " ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 46, "\"> ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var18 string templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(entry.Name) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/file_browser.templ`, Line: 159, Col: 30} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/file_browser.templ`, Line: 154, Col: 30} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 48, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 47, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 49, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 48, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if entry.IsDirectory { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 50, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 49, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -432,19 +432,19 @@ func FileBrowser(data dash.FileBrowserData) templ.Component { var templ_7745c5c3_Var19 string templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(formatBytes(entry.Size)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/file_browser.templ`, Line: 167, Col: 36} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/file_browser.templ`, Line: 162, Col: 36} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 51, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 50, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if entry.IsDirectory { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 52, "Directory") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 51, "Directory") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -452,14 +452,14 @@ func FileBrowser(data dash.FileBrowserData) templ.Component { var templ_7745c5c3_Var20 string templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(getMimeDisplayName(entry.Mime)) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/file_browser.templ`, Line: 175, Col: 44} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/file_browser.templ`, Line: 170, Col: 44} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var20)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 53, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 52, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -467,135 +467,135 @@ func FileBrowser(data dash.FileBrowserData) templ.Component { var templ_7745c5c3_Var21 string templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(entry.ModTime.Format("2006-01-02 15:04")) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/file_browser.templ`, Line: 181, Col: 53} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/file_browser.templ`, Line: 176, Col: 53} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } else { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 54, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 53, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 55, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 56, "\">") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var24 string templ_7745c5c3_Var24, templ_7745c5c3_Err = templ.JoinStringErrs(entry.Mode) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/file_browser.templ`, Line: 187, Col: 146} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/file_browser.templ`, Line: 182, Col: 146} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var24)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 58, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 57, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if !entry.IsDirectory { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 59, " ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 60, "\"> ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 62, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 64, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } else { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 66, "
Empty Directory

This directory contains no files or subdirectories.

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 65, "
Empty Directory

This directory contains no files or subdirectories.

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 67, "
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 66, "
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -603,7 +603,7 @@ func FileBrowser(data dash.FileBrowserData) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 68, " entries per page
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 76, ">200 entries per page
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } if data.HasNextPage { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 78, "Next ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 78, "\" class=\"btn btn-outline-primary\">Next ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } else { - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 80, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 79, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 81, "
Last updated: ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 80, "
Last updated: ") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var31 string templ_7745c5c3_Var31, templ_7745c5c3_Err = templ.JoinStringErrs(data.LastUpdated.Format("2006-01-02 15:04:05")) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/file_browser.templ`, Line: 257, Col: 66} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/file_browser.templ`, Line: 252, Col: 66} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var31)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 82, "
Create New Folder
Folder names cannot contain / or \\ characters.
Create New Folder
Folder names cannot contain / or \\ characters.
Upload Files
Choose one or more files to upload to the current directory. You can select multiple files by holding Ctrl (Cmd on Mac) while clicking.
Upload Files
Choose one or more files to upload to the current directory. You can select multiple files by holding Ctrl (Cmd on Mac) while clicking.
0%
Preparing upload...
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 83, "\">
0%
Preparing upload...
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/weed/admin/view/app/iceberg_table_details.templ b/weed/admin/view/app/iceberg_table_details.templ new file mode 100644 index 000000000..cb4378027 --- /dev/null +++ b/weed/admin/view/app/iceberg_table_details.templ @@ -0,0 +1,376 @@ +package app + +import ( + "fmt" + + "github.com/seaweedfs/seaweedfs/weed/admin/dash" +) + +templ IcebergTableDetails(data dash.IcebergTableDetailsData) { +
+

+ +

+
+
+ +
+
+
+ if data.MetadataError != "" { +
+ { data.MetadataError } +
+ } +
+
+
+
+
+
+
+ Data Files +
+
+ if data.HasDataFileCount { + { formatNumber(data.DataFileCount) } + } else { + - + } +
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+ Total Size +
+
+ if data.HasTotalSize { + { formatBytes(data.TotalSizeBytes) } + } else { + - + } +
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+ Snapshots +
+
+ if data.HasSnapshotCount { + { formatNumber(int64(data.SnapshotCount)) } + } else { + - + } +
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+ Table Metadata +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Table ARN{ data.TableARN }
Format{ data.Format }
Table Location + if data.TableLocation != "" { + { data.TableLocation } + } else { + - + } +
Metadata Location + if data.MetadataLocation != "" { + { data.MetadataLocation } + } else { + - + } +
Created{ data.CreatedAt.Format("2006-01-02 15:04") }
Modified{ data.ModifiedAt.Format("2006-01-02 15:04") }
+
+
+
+
+
+
+
+ Properties +
+
+
+ + + + + + + + + for _, prop := range data.Properties { + + + + + } + if len(data.Properties) == 0 { + + + + } + +
KeyValue
{ prop.Key }{ prop.Value }
No properties available.
+
+
+
+
+
+
+
+
+
+ Schema +
+
+
+
+ + + + + + + + + + + for _, field := range data.SchemaFields { + + + + + + + } + if len(data.SchemaFields) == 0 { + + + + } + +
IDNameTypeRequired
{ fmt.Sprintf("%d", field.ID) }{ field.Name }{ field.Type } + if field.Required { + Yes + } else { + No + } +
No schema available.
+
+
+
+
+
+
+
+
+
+
+ Partitions +
+
+
+
+ + + + + + + + + + + for _, field := range data.PartitionFields { + + + + + + + } + if len(data.PartitionFields) == 0 { + + + + } + +
NameTransformSource IDField ID
{ field.Name }{ field.Transform }{ fmt.Sprintf("%d", field.SourceID) }{ fmt.Sprintf("%d", field.FieldID) }
No partitions defined.
+
+
+
+
+
+
+
+
+
+
+ Snapshot History +
+
+
+
+ + + + + + + + + + + for _, snapshot := range data.Snapshots { + + + + + + + } + if len(data.Snapshots) == 0 { + + + + } + +
Snapshot IDTimestampOperationManifest List
{ fmt.Sprintf("%d", snapshot.SnapshotID) } + if snapshot.Timestamp.IsZero() { + - + } else { + { snapshot.Timestamp.Format("2006-01-02 15:04") } + } + + if snapshot.Operation != "" { + { snapshot.Operation } + } else { + - + } + + if snapshot.ManifestList != "" { + { snapshot.ManifestList } + } else { + - + } +
No snapshots available.
+
+
+
+
+
+ + +} diff --git a/weed/admin/view/app/iceberg_table_details_templ.go b/weed/admin/view/app/iceberg_table_details_templ.go new file mode 100644 index 000000000..991e8c4e7 --- /dev/null +++ b/weed/admin/view/app/iceberg_table_details_templ.go @@ -0,0 +1,618 @@ +// Code generated by templ - DO NOT EDIT. + +// templ: version: v0.3.977 +package app + +//lint:file-ignore SA4006 This context is only used if a nested component is present. + +import "github.com/a-h/templ" +import templruntime "github.com/a-h/templ/runtime" + +import ( + "fmt" + + "github.com/seaweedfs/seaweedfs/weed/admin/dash" +) + +func IcebergTableDetails(data dash.IcebergTableDetailsData) templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { + return templ_7745c5c3_CtxErr + } + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var1 := templ.GetChildren(ctx) + if templ_7745c5c3_Var1 == nil { + templ_7745c5c3_Var1 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "

") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if data.MetadataError != "" { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var10 string + templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(data.MetadataError) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/iceberg_table_details.templ`, Line: 43, Col: 71} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "
Data Files
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if data.HasDataFileCount { + var templ_7745c5c3_Var11 string + templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(formatNumber(data.DataFileCount)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/iceberg_table_details.templ`, Line: 57, Col: 43} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } else { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "-") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "
Total Size
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if data.HasTotalSize { + var templ_7745c5c3_Var12 string + templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(formatBytes(data.TotalSizeBytes)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/iceberg_table_details.templ`, Line: 80, Col: 43} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } else { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "-") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "
Snapshots
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if data.HasSnapshotCount { + var templ_7745c5c3_Var13 string + templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(formatNumber(int64(data.SnapshotCount))) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/iceberg_table_details.templ`, Line: 103, Col: 50} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } else { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "-") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "
Table Metadata
Table ARN") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var14 string + templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(data.TableARN) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/iceberg_table_details.templ`, Line: 130, Col: 52} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "
Format") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var15 string + templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(data.Format) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/iceberg_table_details.templ`, Line: 134, Col: 25} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "
Table Location") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if data.TableLocation != "" { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 21, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var16 string + templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(data.TableLocation) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/iceberg_table_details.templ`, Line: 140, Col: 50} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 22, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } else { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 23, "-") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 24, "
Metadata Location") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if data.MetadataLocation != "" { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 25, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var17 string + templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(data.MetadataLocation) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/iceberg_table_details.templ`, Line: 150, Col: 53} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 26, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } else { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 27, "-") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 28, "
Created") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var18 string + templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(data.CreatedAt.Format("2006-01-02 15:04")) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/iceberg_table_details.templ`, Line: 158, Col: 55} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 29, "
Modified") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var19 string + templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(data.ModifiedAt.Format("2006-01-02 15:04")) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/iceberg_table_details.templ`, Line: 162, Col: 56} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 30, "
Properties
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + for _, prop := range data.Properties { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 31, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + if len(data.Properties) == 0 { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 34, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 35, "
KeyValue
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var20 string + templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(prop.Key) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/iceberg_table_details.templ`, Line: 187, Col: 23} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var20)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 32, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var21 string + templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(prop.Value) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/iceberg_table_details.templ`, Line: 188, Col: 25} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 33, "
No properties available.
Schema
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + for _, field := range data.SchemaFields { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 36, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + if len(data.SchemaFields) == 0 { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 43, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 44, "
IDNameTypeRequired
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var22 string + templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", field.ID)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/iceberg_table_details.templ`, Line: 224, Col: 43} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var22)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 37, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var23 string + templ_7745c5c3_Var23, templ_7745c5c3_Err = templ.JoinStringErrs(field.Name) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/iceberg_table_details.templ`, Line: 225, Col: 26} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var23)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 38, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var24 string + templ_7745c5c3_Var24, templ_7745c5c3_Err = templ.JoinStringErrs(field.Type) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/iceberg_table_details.templ`, Line: 226, Col: 32} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var24)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 39, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if field.Required { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 40, "Yes") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } else { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 41, "No") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 42, "
No schema available.
Partitions
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + for _, field := range data.PartitionFields { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 45, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + if len(data.PartitionFields) == 0 { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 50, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 51, "
NameTransformSource IDField ID
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var25 string + templ_7745c5c3_Var25, templ_7745c5c3_Err = templ.JoinStringErrs(field.Name) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/iceberg_table_details.templ`, Line: 270, Col: 26} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var25)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 46, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var26 string + templ_7745c5c3_Var26, templ_7745c5c3_Err = templ.JoinStringErrs(field.Transform) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/iceberg_table_details.templ`, Line: 271, Col: 31} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var26)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 47, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var27 string + templ_7745c5c3_Var27, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", field.SourceID)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/iceberg_table_details.templ`, Line: 272, Col: 49} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var27)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 48, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var28 string + templ_7745c5c3_Var28, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", field.FieldID)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/iceberg_table_details.templ`, Line: 273, Col: 48} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var28)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 49, "
No partitions defined.
Snapshot History
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + for _, snapshot := range data.Snapshots { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 52, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + if len(data.Snapshots) == 0 { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 62, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 63, "
Snapshot IDTimestampOperationManifest List
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var29 string + templ_7745c5c3_Var29, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", snapshot.SnapshotID)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/iceberg_table_details.templ`, Line: 310, Col: 54} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var29)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 53, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if snapshot.Timestamp.IsZero() { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 54, "-") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } else { + var templ_7745c5c3_Var30 string + templ_7745c5c3_Var30, templ_7745c5c3_Err = templ.JoinStringErrs(snapshot.Timestamp.Format("2006-01-02 15:04")) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/iceberg_table_details.templ`, Line: 315, Col: 59} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var30)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 55, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if snapshot.Operation != "" { + var templ_7745c5c3_Var31 string + templ_7745c5c3_Var31, templ_7745c5c3_Err = templ.JoinStringErrs(snapshot.Operation) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/iceberg_table_details.templ`, Line: 320, Col: 32} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var31)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } else { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 56, "-") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 57, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + if snapshot.ManifestList != "" { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 58, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var32 string + templ_7745c5c3_Var32, templ_7745c5c3_Err = templ.JoinStringErrs(snapshot.ManifestList) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/app/iceberg_table_details.templ`, Line: 327, Col: 55} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var32)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 59, "") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } else { + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 60, "-") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 61, "
No snapshots available.
Drop Table

Are you sure you want to drop the table ?

") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return nil + }) +} + +var _ = templruntime.GeneratedTemplate