UNPKG

datajunction-ui

Version:

DataJunction Metrics Platform UI

271 lines (262 loc) 8.29 kB
import { useEffect, useState } from 'react'; import * as React from 'react'; import EditColumnPopover from './EditColumnPopover'; import EditColumnDescriptionPopover from './EditColumnDescriptionPopover'; import LinkDimensionPopover from './LinkDimensionPopover'; import { labelize } from '../../../utils/form'; import PartitionColumnPopover from './PartitionColumnPopover'; import { Light as SyntaxHighlighter } from 'react-syntax-highlighter'; import { foundation } from 'react-syntax-highlighter/src/styles/hljs'; import { link } from 'fs'; export default function NodeColumnTab({ node, djClient }) { const [attributes, setAttributes] = useState([]); const [dimensions, setDimensions] = useState([]); const [columns, setColumns] = useState([]); const [links, setLinks] = useState([]); useEffect(() => { const fetchData = async () => { if (node) { setColumns(await djClient.columns(node)); } }; fetchData().catch(console.error); }, [djClient, node]); useEffect(() => { const fetchData = async () => { const attributes = await djClient.attributes(); const options = attributes.map(attr => { return { value: attr.name, label: labelize(attr.name) }; }); setAttributes(options); }; fetchData().catch(console.error); }, [djClient]); useEffect(() => { const fetchData = async () => { const dimensions = await djClient.dimensions(); const options = dimensions.map(dim => { return { value: dim.name, label: `${dim.name} (${dim.indegree} links)`, }; }); setDimensions(options); }; fetchData().catch(console.error); }, [djClient]); const showColumnAttributes = col => { return col.attributes.map((attr, idx) => ( <span className="node_type__dimension badge node_type" key={`col-attr-${col.name}-${idx}`} > {attr.attribute_type.name.replace(/_/, ' ')} </span> )); }; const showColumnPartition = col => { if (col.partition) { return ( <> <span className="node_type badge node_type__blank"> <span className="partition_value badge"> <b>Type:</b> {col.partition.type_} </span> <br /> <span className="partition_value badge"> <b>Format:</b> <code>{col.partition.format}</code> </span> <br /> <span className="partition_value badge"> <b>Granularity:</b> <code>{col.partition.granularity}</code> </span> </span> </> ); } return ''; }; const columnList = columns => { return columns?.map(col => { const dimensionLinks = (links.length > 0 ? links : node?.dimension_links) .map(link => [ link.dimension.name, Object.entries(link.foreign_keys).filter( entry => entry[0] === node.name + '.' + col.name, ), ]) .filter(keys => keys[1].length >= 1); const referencedDimensionNode = dimensionLinks.length > 0 ? dimensionLinks[0][0] : null; return ( <tr key={col.name}> <td className="text-start" role="columnheader" aria-label="ColumnName" aria-hidden="false" > {col.name} </td> <td> <span className="" role="columnheader" aria-label="ColumnDisplayName" aria-hidden="false" > {col.display_name} </span> </td> <td> <span className="" role="columnheader" aria-label="ColumnDescription" aria-hidden="false" > {col.description || ''} <EditColumnDescriptionPopover column={col} node={node} onSubmit={async () => { const res = await djClient.node(node.name); setColumns(res.columns); }} /> </span> </td> <td> <span className={`node_type__${ node.type === 'cube' ? col.type : 'transform' } badge node_type`} role="columnheader" aria-label="ColumnType" aria-hidden="false" > {col.type} </span> </td> {node.type !== 'cube' ? ( <td> {dimensionLinks.length > 0 ? dimensionLinks.map(link => ( <span className="rounded-pill badge bg-secondary-soft" style={{ fontSize: '14px' }} key={link[0]} > <a href={`/nodes/${link[0]}`}>{link[0]}</a> </span> )) : ''} <LinkDimensionPopover column={col} dimensionNodes={dimensionLinks.map(link => link[0])} node={node} options={dimensions} onSubmit={async () => { const res = await djClient.node(node.name); setLinks(res.dimension_links); }} /> </td> ) : ( '' )} {node.type !== 'cube' ? ( <td> {showColumnAttributes(col)} <EditColumnPopover column={col} node={node} options={attributes} onSubmit={async () => { const res = await djClient.node(node.name); setColumns(res.columns); }} /> </td> ) : ( '' )} <td> {showColumnPartition(col)} <PartitionColumnPopover column={col} node={node} onSubmit={async () => { const res = await djClient.node(node.name); setColumns(res.columns); }} /> </td> </tr> ); }); }; return ( <> <div className="table-responsive"> <table className="card-inner-table table"> <thead className="fs-7 fw-bold text-gray-400 border-bottom-0"> <tr> <th className="text-start">Column</th> <th>Display Name</th> <th>Description</th> <th>Type</th> {node?.type !== 'cube' ? ( <> <th>Linked Dimension</th> <th>Attributes</th> </> ) : ( '' )} <th>Partition</th> </tr> </thead> <tbody>{columnList(columns)}</tbody> </table> </div> <div> <h3>Linked Dimensions (Custom Join SQL)</h3> <table className="card-inner-table table"> <thead className="fs-7 fw-bold text-gray-400 border-bottom-0"> <tr> <th className="text-start">Dimension Node</th> <th>Join Type</th> <th>Join SQL</th> <th>Role</th> </tr> </thead> <tbody> {node?.dimension_links.map(link => { return ( <tr key={link.dimension.name}> <td> <a href={'/nodes/' + link.dimension.name}> {link.dimension.name} </a> </td> <td>{link.join_type.toUpperCase()}</td> <td style={{ width: '25rem', maxWidth: 'none' }}> <SyntaxHighlighter language="sql" style={foundation} wrapLongLines={true} > {link.join_sql} </SyntaxHighlighter> </td> <td>{link.role}</td> </tr> ); })} </tbody> </table> </div> </> ); }