diff --git a/querybook/webapp/components/DataTableViewOverview/DataTableViewOverview.tsx b/querybook/webapp/components/DataTableViewOverview/DataTableViewOverview.tsx index 01d0e3729..2a4bacc51 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(); @@ -151,22 +157,33 @@ 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 ?? {}; + + // 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]) => { + return ( + + ); + }); const rawMetastoreInfoDOM = table.hive_metastore_description ? (
@@ -209,8 +226,9 @@ export const DataTableViewOverview: React.FC<
     );
     const detailsSection = (
         
+            {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
+            )}
+        
+    );
+};