From 7b40b41e208e548fa7900e7940e0c6e368053565 Mon Sep 17 00:00:00 2001 From: Victor Zhang Date: Wed, 1 May 2024 17:03:28 -0400 Subject: [PATCH 1/5] fix: move slack channel to top of table description --- .../DataTableViewOverview.tsx | 61 ++++++++++++++----- 1 file changed, 45 insertions(+), 16 deletions(-) diff --git a/querybook/webapp/components/DataTableViewOverview/DataTableViewOverview.tsx b/querybook/webapp/components/DataTableViewOverview/DataTableViewOverview.tsx index 01d0e3729..a138feda8 100644 --- a/querybook/webapp/components/DataTableViewOverview/DataTableViewOverview.tsx +++ b/querybook/webapp/components/DataTableViewOverview/DataTableViewOverview.tsx @@ -82,6 +82,24 @@ function useRefreshMetastore(table: IDataTable) { return [handleRefreshTable, isRefreshing] as const; } +function createChannelLinkDOM(customProperties) { + const channelsKey = 'channels'; + const channelsValue = customProperties[channelsKey]?.toString() ?? ''; + const channelsName = channelsValue.slice(1); + const channelLink = `https://pinterest.slack.com/app_redirect?channel=${channelsName}`; + + return channelsValue === '' ? null : ( + + + {channelsValue} + + + ); +} + export interface IQuerybookTableViewOverviewProps { table: IDataTable; tableName: string; @@ -151,22 +169,32 @@ export const DataTableViewOverview: React.FC< ); }); - const customPropertiesDOM = Object.entries( - table.custom_properties ?? {} - ).map(([key, value]) => { - const valueStr = value?.toString() ?? ''; - return ( - - {valueStr && /https?:\/\/[^\s]+/.test(valueStr.trim()) ? ( - - {valueStr} - - ) : ( - valueStr - )} - - ); - }); + const customProperties = table.custom_properties ?? {}; + const channelsDOM = createChannelLinkDOM(customProperties); + + console.log('INSIDE DEVAPP 3'); + + const customPropertiesDOM = Object.entries(customProperties) + .filter(([key, value]) => { + return key !== 'channels'; + }) + .map(([key, value]) => { + const valueStr = value?.toString() ?? ''; + return ( + + {valueStr && /https?:\/\/[^\s]+/.test(valueStr.trim()) ? ( + + {valueStr} + + ) : ( + valueStr + )} + + ); + }); const rawMetastoreInfoDOM = table.hive_metastore_description ? (
@@ -209,6 +237,7 @@ export const DataTableViewOverview: React.FC<
     );
     const detailsSection = (
         
+            {channelsDOM}
             {detailsDOM}
             {customPropertiesDOM}
         

From f73fd39606623ac536d472705ce7e8c11c3c508a Mon Sep 17 00:00:00 2001
From: Victor Zhang 
Date: Wed, 1 May 2024 17:03:28 -0400
Subject: [PATCH 2/5] fix: move slack channel to top of table description

---
 .../DataTableViewOverview.tsx                 | 59 ++++++++++++++-----
 1 file changed, 43 insertions(+), 16 deletions(-)

diff --git a/querybook/webapp/components/DataTableViewOverview/DataTableViewOverview.tsx b/querybook/webapp/components/DataTableViewOverview/DataTableViewOverview.tsx
index 01d0e3729..30933f652 100644
--- a/querybook/webapp/components/DataTableViewOverview/DataTableViewOverview.tsx
+++ b/querybook/webapp/components/DataTableViewOverview/DataTableViewOverview.tsx
@@ -82,6 +82,24 @@ function useRefreshMetastore(table: IDataTable) {
     return [handleRefreshTable, isRefreshing] as const;
 }
 
+function createChannelLinkDOM(customProperties) {
+    const channelsKey = 'channels';
+    const channelsValue = customProperties[channelsKey]?.toString() ?? '';
+    const channelsName = channelsValue.slice(1);
+    const channelLink = `https://pinterest.slack.com/app_redirect?channel=${channelsName}`;
+
+    return channelsValue === '' ? null : (
+        
+            
+                {channelsValue}
+            
+        
+    );
+}
+
 export interface IQuerybookTableViewOverviewProps {
     table: IDataTable;
     tableName: string;
@@ -151,22 +169,30 @@ export const DataTableViewOverview: React.FC<
             );
         });
 
-    const customPropertiesDOM = Object.entries(
-        table.custom_properties ?? {}
-    ).map(([key, value]) => {
-        const valueStr = value?.toString() ?? '';
-        return (
-            
-                {valueStr && /https?:\/\/[^\s]+/.test(valueStr.trim()) ? (
-                    
-                        {valueStr}
-                    
-                ) : (
-                    valueStr
-                )}
-            
-        );
-    });
+    const customProperties = table.custom_properties ?? {};
+    const channelsDOM = createChannelLinkDOM(customProperties);
+
+    const customPropertiesDOM = Object.entries(customProperties)
+        .filter(([key, value]) => {
+            return key !== 'channels';
+        })
+        .map(([key, value]) => {
+            const valueStr = value?.toString() ?? '';
+            return (
+                
+                    {valueStr && /https?:\/\/[^\s]+/.test(valueStr.trim()) ? (
+                        
+                            {valueStr}
+                        
+                    ) : (
+                        valueStr
+                    )}
+                
+            );
+        });
 
     const rawMetastoreInfoDOM = table.hive_metastore_description ? (
         
@@ -209,6 +235,7 @@ export const DataTableViewOverview: React.FC<
     );
     const detailsSection = (
         
+            {channelsDOM}
             {detailsDOM}
             {customPropertiesDOM}
         

From eb7a6f734ee1eaf800d095df68fa8bf8e58adb26 Mon Sep 17 00:00:00 2001
From: Victor Zhang 
Date: Fri, 3 May 2024 12:11:20 -0400
Subject: [PATCH 3/5] address comments

---
 .../DataTableViewOverview/DataTableViewOverview.tsx         | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/querybook/webapp/components/DataTableViewOverview/DataTableViewOverview.tsx b/querybook/webapp/components/DataTableViewOverview/DataTableViewOverview.tsx
index 30933f652..eb6677a08 100644
--- a/querybook/webapp/components/DataTableViewOverview/DataTableViewOverview.tsx
+++ b/querybook/webapp/components/DataTableViewOverview/DataTableViewOverview.tsx
@@ -85,17 +85,13 @@ function useRefreshMetastore(table: IDataTable) {
 function createChannelLinkDOM(customProperties) {
     const channelsKey = 'channels';
     const channelsValue = customProperties[channelsKey]?.toString() ?? '';
-    const channelsName = channelsValue.slice(1);
-    const channelLink = `https://pinterest.slack.com/app_redirect?channel=${channelsName}`;
 
     return channelsValue === '' ? null : (
         
-            
-                {channelsValue}
-            
+            {channelsValue}
         
     );
 }

From 56828c975f5133558b6160f86c63f2d351ad4575 Mon Sep 17 00:00:00 2001
From: Victor Zhang 
Date: Fri, 3 May 2024 20:38:36 -0400
Subject: [PATCH 4/5] use pinnedCustomProperties to order properties

---
 .../DataTableViewOverview.tsx                 | 74 +++++++++----------
 1 file changed, 36 insertions(+), 38 deletions(-)

diff --git a/querybook/webapp/components/DataTableViewOverview/DataTableViewOverview.tsx b/querybook/webapp/components/DataTableViewOverview/DataTableViewOverview.tsx
index eb6677a08..fd81bab1a 100644
--- a/querybook/webapp/components/DataTableViewOverview/DataTableViewOverview.tsx
+++ b/querybook/webapp/components/DataTableViewOverview/DataTableViewOverview.tsx
@@ -56,6 +56,26 @@ const dataTableDetailsRows = [
     'column_count',
 ];
 
+/**
+ * Any custom properties in this array will be shown on top following the order of the array
+ */
+const pinnedCustomProperties = ['channels'];
+
+function createKeyContentDisplayElement(key: string, value: string | number) {
+    const valueStr = value?.toString() ?? '';
+    return (
+        
+            {valueStr && /https?:\/\/[^\s]+/.test(valueStr.trim()) ? (
+                
+                    {valueStr}
+                
+            ) : (
+                valueStr
+            )}
+        
+    );
+}
+
 function useRefreshMetastore(table: IDataTable) {
     const dispatch = useDispatch();
     const isMounted = useMounted();
@@ -82,20 +102,6 @@ function useRefreshMetastore(table: IDataTable) {
     return [handleRefreshTable, isRefreshing] as const;
 }
 
-function createChannelLinkDOM(customProperties) {
-    const channelsKey = 'channels';
-    const channelsValue = customProperties[channelsKey]?.toString() ?? '';
-
-    return channelsValue === '' ? null : (
-        
-            {channelsValue}
-        
-    );
-}
-
 export interface IQuerybookTableViewOverviewProps {
     table: IDataTable;
     tableName: string;
@@ -165,30 +171,22 @@ export const DataTableViewOverview: React.FC<
             );
         });
 
-    const customProperties = table.custom_properties ?? {};
-    const channelsDOM = createChannelLinkDOM(customProperties);
+    const customProperties = Object.entries(table.custom_properties ?? {});
 
-    const customPropertiesDOM = Object.entries(customProperties)
-        .filter(([key, value]) => {
-            return key !== 'channels';
+    // Get pinned custom properties and display based on order of pinnedCustomProperties
+    const pinnedPropertiesDOM = customProperties
+        .filter(([key]) => pinnedCustomProperties.includes(key))
+        .sort(([key1], [key2]) => {
+            const aIndex = pinnedCustomProperties.indexOf(key1);
+            const bIndex = pinnedCustomProperties.indexOf(key2);
+            return aIndex - bIndex;
         })
-        .map(([key, value]) => {
-            const valueStr = value?.toString() ?? '';
-            return (
-                
-                    {valueStr && /https?:\/\/[^\s]+/.test(valueStr.trim()) ? (
-                        
-                            {valueStr}
-                        
-                    ) : (
-                        valueStr
-                    )}
-                
-            );
-        });
+        .map(([key, value]) => createKeyContentDisplayElement(key, value));
+
+    // Get unpinned custom properties
+    const unpinnedPropertiesDOM = customProperties
+        .filter(([key]) => !pinnedCustomProperties.includes(key))
+        .map(([key, value]) => createKeyContentDisplayElement(key, value));
 
     const rawMetastoreInfoDOM = table.hive_metastore_description ? (
         
@@ -231,9 +229,9 @@ export const DataTableViewOverview: React.FC<
     );
     const detailsSection = (
         
-            {channelsDOM}
+            {pinnedPropertiesDOM}
             {detailsDOM}
-            {customPropertiesDOM}
+            {unpinnedPropertiesDOM}
         
     );
 

From 58daca66d9dd2cf6c1d7c6904688a1aade153381 Mon Sep 17 00:00:00 2001
From: Victor Zhang 
Date: Fri, 3 May 2024 20:38:36 -0400
Subject: [PATCH 5/5] use pinnedCustomProperties to order properties

---
 .../DataTableViewOverview.tsx                 | 57 +++++++------------
 .../KeyContentDisplayLink.tsx                 | 27 +++++++++
 2 files changed, 47 insertions(+), 37 deletions(-)
 create mode 100644 querybook/webapp/ui/KeyContentDisplay/KeyContentDisplayLink.tsx

diff --git a/querybook/webapp/components/DataTableViewOverview/DataTableViewOverview.tsx b/querybook/webapp/components/DataTableViewOverview/DataTableViewOverview.tsx
index eb6677a08..1c6e8c569 100644
--- a/querybook/webapp/components/DataTableViewOverview/DataTableViewOverview.tsx
+++ b/querybook/webapp/components/DataTableViewOverview/DataTableViewOverview.tsx
@@ -25,7 +25,7 @@ import {
 } from 'const/metastore';
 import { useMounted } from 'hooks/useMounted';
 import { Nullable } from 'lib/typescript';
-import { titleize } from 'lib/utils';
+import { isValidUrl, titleize } from 'lib/utils';
 import { generateFormattedDate } from 'lib/utils/datetime';
 import { getAppName } from 'lib/utils/global';
 import { getHumanReadableByteSize } from 'lib/utils/number';
@@ -34,6 +34,7 @@ import { refreshDataTableInMetastore } from 'redux/dataSources/action';
 import { SoftButton, TextButton } from 'ui/Button/Button';
 import { EditableTextField } from 'ui/EditableTextField/EditableTextField';
 import { KeyContentDisplay } from 'ui/KeyContentDisplay/KeyContentDisplay';
+import { KeyContentDisplayLink } from 'ui/KeyContentDisplay/KeyContentDisplayLink';
 import { Link } from 'ui/Link/Link';
 import { LoadingRow } from 'ui/Loading/Loading';
 import { Message } from 'ui/Message/Message';
@@ -56,6 +57,11 @@ const dataTableDetailsRows = [
     'column_count',
 ];
 
+/**
+ * Any custom properties in this array will be shown on top following the order of the array
+ */
+const pinnedCustomProperties = ['channels'];
+
 function useRefreshMetastore(table: IDataTable) {
     const dispatch = useDispatch();
     const isMounted = useMounted();
@@ -82,20 +88,6 @@ function useRefreshMetastore(table: IDataTable) {
     return [handleRefreshTable, isRefreshing] as const;
 }
 
-function createChannelLinkDOM(customProperties) {
-    const channelsKey = 'channels';
-    const channelsValue = customProperties[channelsKey]?.toString() ?? '';
-
-    return channelsValue === '' ? null : (
-        
-            {channelsValue}
-        
-    );
-}
-
 export interface IQuerybookTableViewOverviewProps {
     table: IDataTable;
     tableName: string;
@@ -166,28 +158,19 @@ export const DataTableViewOverview: React.FC<
         });
 
     const customProperties = table.custom_properties ?? {};
-    const channelsDOM = createChannelLinkDOM(customProperties);
 
-    const customPropertiesDOM = Object.entries(customProperties)
-        .filter(([key, value]) => {
-            return key !== 'channels';
-        })
+    // Get pinned custom properties and display based on order of pinnedCustomProperties
+    const pinnedPropertiesDOM = pinnedCustomProperties
+        .filter((p) => p in customProperties)
+        .map((key) => {
+            const value = customProperties[key];
+            return ;
+        });
+
+    const otherPropertiesDOM = Object.entries(customProperties)
+        .filter(([key]) => !pinnedCustomProperties.includes(key))
         .map(([key, value]) => {
-            const valueStr = value?.toString() ?? '';
-            return (
-                
-                    {valueStr && /https?:\/\/[^\s]+/.test(valueStr.trim()) ? (
-                        
-                            {valueStr}
-                        
-                    ) : (
-                        valueStr
-                    )}
-                
-            );
+            return ;
         });
 
     const rawMetastoreInfoDOM = table.hive_metastore_description ? (
@@ -231,9 +214,9 @@ export const DataTableViewOverview: React.FC<
     );
     const detailsSection = (
         
-            {channelsDOM}
+            {pinnedPropertiesDOM}
             {detailsDOM}
-            {customPropertiesDOM}
+            {otherPropertiesDOM}
         
     );
 
diff --git a/querybook/webapp/ui/KeyContentDisplay/KeyContentDisplayLink.tsx b/querybook/webapp/ui/KeyContentDisplay/KeyContentDisplayLink.tsx
new file mode 100644
index 000000000..6a930f4c4
--- /dev/null
+++ b/querybook/webapp/ui/KeyContentDisplay/KeyContentDisplayLink.tsx
@@ -0,0 +1,27 @@
+import * as React from 'react';
+
+import { isValidUrl, titleize } from 'lib/utils';
+import { Link } from 'ui/Link/Link';
+
+import { KeyContentDisplay } from './KeyContentDisplay';
+
+export const KeyContentDisplayLink: React.FunctionComponent<{
+    keyString: string;
+    value: string | number;
+}> = ({ keyString, value }) => {
+    const valueStr = value?.toString() ?? '';
+    return (
+        
+            {valueStr && isValidUrl(valueStr.trim()) ? (
+                
+                    {valueStr}
+                
+            ) : (
+                valueStr
+            )}
+        
+    );
+};