22 * Copyright (c) 2016-2020 LabKey Corporation. All rights reserved. No portion of this work may be reproduced in
33 * any form or by any electronic or mechanical means without written permission from LabKey Corporation.
44 */
5- import React , { FC , memo , PureComponent , ReactNode , useCallback , useMemo , useState } from 'react' ;
5+ import React , { FC , memo , ReactNode , useCallback , useMemo , useState } from 'react' ;
66import { List } from 'immutable' ;
77
88import { Tab , Tabs } from '../../../Tabs' ;
@@ -12,6 +12,7 @@ import {
1212 isAliquotNode ,
1313 LineageIOWithMetadata ,
1414 LineageNode ,
15+ LineageNodeCollection ,
1516 LineageNodeCollectionByType ,
1617} from '../models' ;
1718import { LineageOptions } from '../types' ;
@@ -32,47 +33,21 @@ interface LineageNodeDetailProps {
3233 seed : string ;
3334}
3435
35- interface LineageNodeDetailState {
36- stepIdx : number ;
37- tabKey : string ;
38- }
39-
40- const initialState : LineageNodeDetailState = {
41- stepIdx : undefined ,
42- tabKey : 'details' ,
43- } ;
44-
45- export class LineageNodeDetail extends PureComponent < LineageNodeDetailProps , LineageNodeDetailState > {
46- readonly state : LineageNodeDetailState = initialState ;
47-
48- componentDidUpdate ( prevProps : Readonly < LineageNodeDetailProps > ) : void {
49- const prevNode = prevProps . node ;
50- const { node } = this . props ;
36+ export const LineageNodeDetail : FC < LineageNodeDetailProps > = memo ( props => {
37+ const { seed, node, highlightNode, lineageOptions } = props ;
38+ const { isRun, restricted } = node ;
39+ const [ stepIdx , setStepIdx ] = useState < number > ( undefined ) ;
40+ const [ tabKey , setTabKey ] = useState < string > ( 'details' ) ;
41+ const onBack = useCallback ( ( ) => setStepIdx ( undefined ) , [ ] ) ;
5142
52- if ( ( prevNode . isRun || node . isRun ) && prevNode . lsid !== node . lsid ) {
53- this . setState ( initialState ) ;
54- }
43+ if ( isRun && stepIdx !== undefined ) {
44+ return < RunStepNodeDetail node = { node } onBack = { onBack } stepIdx = { stepIdx } /> ;
5545 }
5646
57- changeTab = ( tabKey : string ) : void => {
58- this . setState ( { tabKey } ) ;
59- } ;
60-
61- selectStep = ( stepIdx : number ) : void => {
62- this . setState ( { stepIdx } ) ;
63- } ;
64-
65- render ( ) : ReactNode {
66- const { seed, node, highlightNode, lineageOptions } = this . props ;
67- const { stepIdx, tabKey } = this . state ;
68-
69- if ( node . isRun && stepIdx !== undefined ) {
70- return < RunStepNodeDetail node = { node } onBack = { ( ) => this . selectStep ( undefined ) } stepIdx = { stepIdx } /> ;
71- }
72-
73- const nodeDetails = (
74- < >
75- < LineageDetail item = { node } />
47+ const nodeDetails = (
48+ < >
49+ < LineageDetail item = { node } />
50+ { ! restricted && (
7651 < LineageSummary
7752 { ...lineageOptions }
7853 containerPath = { node . containerPath }
@@ -81,29 +56,30 @@ export class LineageNodeDetail extends PureComponent<LineageNodeDetailProps, Lin
8156 lsid = { node . lsid }
8257 prefetchSeed = { false }
8358 />
84- </ >
85- ) ;
86-
87- return (
88- < div className = "lineage-node-detail" >
89- < NodeDetailHeader node = { node } seed = { seed } />
90- { node . isRun ? (
91- < Tabs activeKey = { tabKey } onSelect = { this . changeTab } >
92- < Tab eventKey = "details" title = "Details" >
93- { nodeDetails }
94- </ Tab >
95- < Tab eventKey = "runProperties" title = "Run Properties" >
96- < DetailsListSteps node = { node } onSelect = { this . selectStep } />
97- < DetailsListLineageIO item = { node } />
98- </ Tab >
99- </ Tabs >
100- ) : (
101- nodeDetails
102- ) }
103- </ div >
104- ) ;
105- }
106- }
59+ ) }
60+ </ >
61+ ) ;
62+
63+ return (
64+ < div className = "lineage-node-detail" >
65+ < NodeDetailHeader node = { node } seed = { seed } />
66+ { isRun && ! restricted ? (
67+ < Tabs activeKey = { tabKey } onSelect = { setTabKey } >
68+ < Tab eventKey = "details" title = "Details" >
69+ { nodeDetails }
70+ </ Tab >
71+ < Tab eventKey = "runProperties" title = "Run Properties" >
72+ < DetailsListSteps node = { node } onSelect = { setStepIdx } />
73+ < DetailsListLineageIO item = { node } />
74+ </ Tab >
75+ </ Tabs >
76+ ) : (
77+ nodeDetails
78+ ) }
79+ </ div >
80+ ) ;
81+ } ) ;
82+ LineageNodeDetail . displayName = 'LineageNodeDetail' ;
10783
10884interface ClusterNodeDetailProps {
10985 highlightNode ?: string ;
@@ -113,52 +89,43 @@ interface ClusterNodeDetailProps {
11389 parentNodeName ?: string ;
11490}
11591
116- export class ClusterNodeDetail extends PureComponent < ClusterNodeDetailProps > {
117- static getGroupDisplayName ( nodesByType , groupName , parentNodeName ?) {
118- const group = nodesByType [ groupName ] ;
119- const isAliquot = isAliquotNode ( group ) ;
120- const aliquotDisplayName = ( parentNodeName ? parentNodeName + ' ' : '' ) + 'Aliquots' ;
121- return isAliquot ? aliquotDisplayName : group . displayType ;
122- }
92+ function getGroupDisplayName ( nodeCollection : LineageNodeCollection , parentNodeName ?: string ) : string {
93+ if ( isAliquotNode ( nodeCollection ) ) return ( parentNodeName ? parentNodeName + ' ' : '' ) + 'Aliquots' ;
94+ return nodeCollection . displayType ;
95+ }
12396
124- render ( ) : ReactNode {
125- const { highlightNode, nodes, options, parentNodeName } = this . props ;
126-
127- const nodesByType = this . props . nodesByType ?? createLineageNodeCollections ( nodes , options ) ;
128- const groups = Object . keys ( nodesByType ) . sort ( ) ;
129-
130- let iconURL ;
131- let title ;
132- if ( groups . length === 1 ) {
133- title = nodes . length + ' ' + ClusterNodeDetail . getGroupDisplayName ( nodesByType , groups [ 0 ] ) ;
134- iconURL = nodes [ 0 ] . iconProps . iconURL ;
135- } else {
136- title = nodes . length + ' items of different types' ;
137- iconURL = 'default' ;
138- }
139-
140- return (
141- < div className = "cluster-node-detail" >
142- < DetailHeader header = { title } iconSrc = { iconURL } />
143- { groups . map ( groupName => {
144- const groupDisplayName = ClusterNodeDetail . getGroupDisplayName (
145- nodesByType ,
146- groupName ,
147- parentNodeName
148- ) ;
149- return (
150- < DetailsListNodes
151- highlightNode = { highlightNode }
152- key = { groupName }
153- nodes = { nodesByType [ groupName ] }
154- title = { groupDisplayName }
155- />
156- ) ;
157- } ) }
158- </ div >
159- ) ;
97+ export const ClusterNodeDetail : FC < ClusterNodeDetailProps > = memo ( props => {
98+ const { highlightNode, nodes, options, parentNodeName } = props ;
99+ const { groups, nodesByType } = useMemo ( ( ) => {
100+ const nodesByType = props . nodesByType ?? createLineageNodeCollections ( nodes , options ) ;
101+ return { groups : Object . keys ( nodesByType ) . sort ( ) , nodesByType } ;
102+ } , [ nodes , options , props . nodesByType ] ) ;
103+
104+ let iconURL : string ;
105+ let title : ReactNode ;
106+ if ( groups . length === 1 ) {
107+ title = nodes . length + ' ' + getGroupDisplayName ( nodesByType [ groups [ 0 ] ] ) ;
108+ iconURL = nodes [ 0 ] . iconProps . iconURL ;
109+ } else {
110+ title = nodes . length + ' items of different types' ;
111+ iconURL = 'default' ;
160112 }
161- }
113+
114+ return (
115+ < div className = "cluster-node-detail" >
116+ < DetailHeader header = { title } iconSrc = { iconURL } />
117+ { groups . map ( groupName => (
118+ < DetailsListNodes
119+ highlightNode = { highlightNode }
120+ key = { groupName }
121+ nodes = { nodesByType [ groupName ] }
122+ title = { getGroupDisplayName ( nodesByType [ groupName ] , parentNodeName ) }
123+ />
124+ ) ) }
125+ </ div >
126+ ) ;
127+ } ) ;
128+ ClusterNodeDetail . displayName = 'ClusterNodeDetail' ;
162129
163130interface RunStepNodeDetailProps {
164131 node : LineageNode ;
0 commit comments