@@ -9,16 +9,20 @@ import { dateStringUTC } from 'lib/DateUtils';
99import getFileName from 'lib/getFileName' ;
1010import Parse from 'parse' ;
1111import Pill from 'components/Pill/Pill.react' ;
12- import React , { useEffect , useRef }
13- from 'react' ;
12+ import React , { Component } from 'react' ;
1413import styles from 'components/BrowserCell/BrowserCell.scss' ;
1514import { unselectable } from 'stylesheets/base.scss' ;
1615
17- let BrowserCell = ( { type, value, hidden, width, current, onSelect, onEditChange, setRelation, onPointerClick } ) => {
18- const cellRef = current ? useRef ( ) : null ;
19- if ( current ) {
20- useEffect ( ( ) => {
21- const node = cellRef . current ;
16+ export default class BrowserCell extends Component {
17+ constructor ( ) {
18+ super ( ) ;
19+
20+ this . cellRef = React . createRef ( ) ;
21+ }
22+
23+ componentDidUpdate ( ) {
24+ if ( this . props . current ) {
25+ const node = this . cellRef . current ;
2226 const { left, right, bottom, top } = node . getBoundingClientRect ( ) ;
2327
2428 // Takes into consideration Sidebar width when over 980px wide.
@@ -28,118 +32,137 @@ let BrowserCell = ({ type, value, hidden, width, current, onSelect, onEditChange
2832 const topBoundary = 126 ;
2933
3034 if ( left < leftBoundary || right > window . innerWidth ) {
31- node . scrollIntoView ( { behavior : 'smooth' , block : 'nearest' , inline : 'start' } ) ;
35+ node . scrollIntoView ( { block : 'nearest' , inline : 'start' } ) ;
3236 } else if ( top < topBoundary || bottom > window . innerHeight ) {
33- node . scrollIntoView ( { behavior : 'smooth' , block : 'nearest' , inline : 'nearest' } ) ;
37+ node . scrollIntoView ( { block : 'nearest' , inline : 'nearest' } ) ;
3438 }
35- } ) ;
39+ }
3640 }
3741
38- let content = value ;
39- let classes = [ styles . cell , unselectable ] ;
40- if ( hidden ) {
41- content = '(hidden)' ;
42- classes . push ( styles . empty ) ;
43- } else if ( value === undefined ) {
44- if ( type === 'ACL' ) {
45- content = 'Public Read + Write' ;
46- } else {
47- content = '(undefined)' ;
48- classes . push ( styles . empty ) ;
49- }
50- } else if ( value === null ) {
51- content = '(null)' ;
52- classes . push ( styles . empty ) ;
53- } else if ( value === '' ) {
54- content = < span > </ span > ;
55- classes . push ( styles . empty ) ;
56- } else if ( type === 'Pointer' ) {
57- if ( value && value . __type ) {
58- const object = new Parse . Object ( value . className ) ;
59- object . id = value . objectId ;
60- value = object ;
42+ shouldComponentUpdate ( nextProps ) {
43+ const shallowVerifyProps = [ ...new Set ( Object . keys ( this . props ) . concat ( Object . keys ( nextProps ) ) ) ]
44+ . filter ( propName => propName !== 'value' ) ;
45+ if ( shallowVerifyProps . some ( propName => this . props [ propName ] !== nextProps [ propName ] ) ) {
46+ return true ;
6147 }
62- content = (
63- < a href = 'javascript:;' onClick = { onPointerClick . bind ( undefined , value ) } >
64- < Pill value = { value . id } />
65- </ a >
66- ) ;
67- } else if ( type === 'Date' ) {
68- if ( typeof value === 'object' && value . __type ) {
69- value = new Date ( value . iso ) ;
70- } else if ( typeof value === 'string' ) {
71- value = new Date ( value ) ;
48+ const { value } = this . props ;
49+ const { value : nextValue } = nextProps ;
50+ if ( typeof value !== typeof nextValue ) {
51+ return true ;
7252 }
73- content = dateStringUTC ( value ) ;
74- } else if ( type === 'Boolean' ) {
75- content = value ? 'True' : 'False' ;
76- } else if ( type === 'Object' || type === 'Bytes' || type === 'Array' ) {
77- content = JSON . stringify ( value ) ;
78- } else if ( type === 'File' ) {
79- if ( value . url ( ) ) {
80- content = < Pill value = { getFileName ( value ) } /> ;
81- } else {
82- content = < Pill value = { 'Uploading\u2026' } /> ;
53+ const isRefDifferent = value !== nextValue ;
54+ if ( isRefDifferent && typeof value === 'object' ) {
55+ return JSON . stringify ( value ) !== JSON . stringify ( nextValue ) ;
8356 }
84- } else if ( type === 'ACL' ) {
85- let pieces = [ ] ;
86- let json = value . toJSON ( ) ;
87- if ( Object . prototype . hasOwnProperty . call ( json , '*' ) ) {
88- if ( json [ '*' ] . read && json [ '*' ] . write ) {
89- pieces . push ( 'Public Read + Write' ) ;
90- } else if ( json [ '*' ] . read ) {
91- pieces . push ( 'Public Read' ) ;
92- } else if ( json [ '*' ] . write ) {
93- pieces . push ( 'Public Write' ) ;
57+ return isRefDifferent ;
58+ }
59+
60+ render ( ) {
61+ let { type, value, hidden, width, current, onSelect, onEditChange, setRelation, onPointerClick, row, col } = this . props ;
62+ let content = value ;
63+ let classes = [ styles . cell , unselectable ] ;
64+ if ( hidden ) {
65+ content = '(hidden)' ;
66+ classes . push ( styles . empty ) ;
67+ } else if ( value === undefined ) {
68+ if ( type === 'ACL' ) {
69+ content = 'Public Read + Write' ;
70+ } else {
71+ content = '(undefined)' ;
72+ classes . push ( styles . empty ) ;
9473 }
95- }
96- for ( let role in json ) {
97- if ( role !== '*' ) {
98- pieces . push ( role ) ;
74+ } else if ( value === null ) {
75+ content = '(null)' ;
76+ classes . push ( styles . empty ) ;
77+ } else if ( value === '' ) {
78+ content = < span > </ span > ;
79+ classes . push ( styles . empty ) ;
80+ } else if ( type === 'Pointer' ) {
81+ if ( value && value . __type ) {
82+ const object = new Parse . Object ( value . className ) ;
83+ object . id = value . objectId ;
84+ value = object ;
85+ }
86+ content = (
87+ < a href = 'javascript:;' onClick = { onPointerClick . bind ( undefined , value ) } >
88+ < Pill value = { value . id } />
89+ </ a >
90+ ) ;
91+ } else if ( type === 'Date' ) {
92+ if ( typeof value === 'object' && value . __type ) {
93+ value = new Date ( value . iso ) ;
94+ } else if ( typeof value === 'string' ) {
95+ value = new Date ( value ) ;
9996 }
97+ content = dateStringUTC ( value ) ;
98+ } else if ( type === 'Boolean' ) {
99+ content = value ? 'True' : 'False' ;
100+ } else if ( type === 'Object' || type === 'Bytes' || type === 'Array' ) {
101+ content = JSON . stringify ( value ) ;
102+ } else if ( type === 'File' ) {
103+ if ( value . url ( ) ) {
104+ content = < Pill value = { getFileName ( value ) } /> ;
105+ } else {
106+ content = < Pill value = { 'Uploading\u2026' } /> ;
107+ }
108+ } else if ( type === 'ACL' ) {
109+ let pieces = [ ] ;
110+ let json = value . toJSON ( ) ;
111+ if ( Object . prototype . hasOwnProperty . call ( json , '*' ) ) {
112+ if ( json [ '*' ] . read && json [ '*' ] . write ) {
113+ pieces . push ( 'Public Read + Write' ) ;
114+ } else if ( json [ '*' ] . read ) {
115+ pieces . push ( 'Public Read' ) ;
116+ } else if ( json [ '*' ] . write ) {
117+ pieces . push ( 'Public Write' ) ;
118+ }
119+ }
120+ for ( let role in json ) {
121+ if ( role !== '*' ) {
122+ pieces . push ( role ) ;
123+ }
124+ }
125+ if ( pieces . length === 0 ) {
126+ pieces . push ( 'Master Key Only' ) ;
127+ }
128+ content = pieces . join ( ', ' ) ;
129+ } else if ( type === 'GeoPoint' ) {
130+ content = `(${ value . latitude } , ${ value . longitude } )` ;
131+ } else if ( type === 'Polygon' ) {
132+ content = value . coordinates . map ( coord => `(${ coord } )` )
133+ } else if ( type === 'Relation' ) {
134+ content = (
135+ < div style = { { textAlign : 'center' , cursor : 'pointer' } } >
136+ < Pill onClick = { ( ) => setRelation ( value ) } value = 'View relation' />
137+ </ div >
138+ ) ;
100139 }
101- if ( pieces . length === 0 ) {
102- pieces . push ( 'Master Key Only' ) ;
140+
141+ if ( current ) {
142+ classes . push ( styles . current ) ;
103143 }
104- content = pieces . join ( ', ' ) ;
105- } else if ( type === 'GeoPoint' ) {
106- content = `(${ value . latitude } , ${ value . longitude } )` ;
107- } else if ( type === 'Polygon' ) {
108- content = value . coordinates . map ( coord => `(${ coord } )` )
109- } else if ( type === 'Relation' ) {
110- content = (
111- < div style = { { textAlign : 'center' , cursor : 'pointer' } } >
112- < Pill onClick = { ( ) => setRelation ( value ) } value = 'View relation' />
113- </ div >
144+ return (
145+ < span
146+ ref = { this . cellRef }
147+ className = { classes . join ( ' ' ) }
148+ style = { { width } }
149+ onClick = { ( ) => onSelect ( { row, col } ) }
150+ onDoubleClick = { ( ) => {
151+ if ( type !== 'Relation' ) {
152+ onEditChange ( true )
153+ }
154+ } }
155+ onTouchEnd = { e => {
156+ if ( current && type !== 'Relation' ) {
157+ // The touch event may trigger an unwanted change in the column value
158+ if ( [ 'ACL' , 'Boolean' , 'File' ] . includes ( type ) ) {
159+ e . preventDefault ( ) ;
160+ }
161+ onEditChange ( true ) ;
162+ }
163+ } } >
164+ { content }
165+ </ span >
114166 ) ;
115167 }
116-
117- if ( current ) {
118- classes . push ( styles . current ) ;
119- }
120- return (
121- < span
122- ref = { cellRef }
123- className = { classes . join ( ' ' ) }
124- style = { { width } }
125- onClick = { onSelect }
126- onDoubleClick = { ( ) => {
127- if ( type !== 'Relation' ) {
128- onEditChange ( true )
129- }
130- } }
131- onTouchEnd = { e => {
132- if ( current && type !== 'Relation' ) {
133- // The touch event may trigger an unwanted change in the column value
134- if ( [ 'ACL' , 'Boolean' , 'File' ] . includes ( type ) ) {
135- e . preventDefault ( ) ;
136- }
137- onEditChange ( true ) ;
138- }
139- } } >
140- { content }
141- </ span >
142- ) ;
143- } ;
144-
145- export default BrowserCell ;
168+ }
0 commit comments