@@ -5,9 +5,146 @@ import { bindActionCreators } from 'redux';
55import { Link } from 'react-router' ;
66import { Helmet } from 'react-helmet' ;
77import prettyBytes from 'pretty-bytes' ;
8+ import InlineSVG from 'react-inlinesvg' ;
89
910import Loader from '../../App/components/loader' ;
1011import * as AssetActions from '../actions/assets' ;
12+ import downFilledTriangle from '../../../images/down-filled-triangle.svg' ;
13+
14+ class AssetListRowBase extends React . Component {
15+ constructor ( props ) {
16+ super ( props ) ;
17+ this . state = {
18+ isFocused : false ,
19+ optionsOpen : false
20+ } ;
21+ }
22+
23+ onFocusComponent = ( ) => {
24+ this . setState ( { isFocused : true } ) ;
25+ }
26+
27+ onBlurComponent = ( ) => {
28+ this . setState ( { isFocused : false } ) ;
29+ setTimeout ( ( ) => {
30+ if ( ! this . state . isFocused ) {
31+ this . closeOptions ( ) ;
32+ }
33+ } , 200 ) ;
34+ }
35+
36+ openOptions = ( ) => {
37+ this . setState ( {
38+ optionsOpen : true
39+ } ) ;
40+ }
41+
42+ closeOptions = ( ) => {
43+ this . setState ( {
44+ optionsOpen : false
45+ } ) ;
46+ }
47+
48+ toggleOptions = ( ) => {
49+ if ( this . state . optionsOpen ) {
50+ this . closeOptions ( ) ;
51+ } else {
52+ this . openOptions ( ) ;
53+ }
54+ }
55+
56+ handleDropdownOpen = ( ) => {
57+ this . closeOptions ( ) ;
58+ this . openOptions ( ) ;
59+ }
60+
61+ handleAssetDelete = ( ) => {
62+ const { key, name } = this . props . asset ;
63+ this . closeOptions ( ) ;
64+ if ( window . confirm ( `Are you sure you want to delete "${ name } "?` ) ) {
65+ this . props . deleteAssetRequest ( key ) ;
66+ }
67+ }
68+
69+ render ( ) {
70+ const { asset, username } = this . props ;
71+ const { optionsOpen } = this . state ;
72+ return (
73+ < tr className = "asset-table__row" key = { asset . key } >
74+ < th scope = "row" >
75+ < Link to = { asset . url } target = "_blank" >
76+ { asset . name }
77+ </ Link >
78+ </ th >
79+ < td > { prettyBytes ( asset . size ) } </ td >
80+ < td >
81+ { asset . sketchId && < Link to = { `/${ username } /sketches/${ asset . sketchId } ` } > { asset . sketchName } </ Link > }
82+ </ td >
83+ < td className = "asset-table__dropdown-column" >
84+ < button
85+ className = "asset-table__dropdown-button"
86+ onClick = { this . toggleOptions }
87+ onBlur = { this . onBlurComponent }
88+ onFocus = { this . onFocusComponent }
89+ >
90+ < InlineSVG src = { downFilledTriangle } alt = "Menu" />
91+ </ button >
92+ { optionsOpen &&
93+ < ul
94+ className = "asset-table__action-dialogue"
95+ >
96+ < li >
97+ < button
98+ className = "asset-table__action-option"
99+ onClick = { this . handleAssetDelete }
100+ onBlur = { this . onBlurComponent }
101+ onFocus = { this . onFocusComponent }
102+ >
103+ Delete
104+ </ button >
105+ </ li >
106+ < li >
107+ < Link
108+ to = { asset . url }
109+ target = "_blank"
110+ onBlur = { this . onBlurComponent }
111+ onFocus = { this . onFocusComponent }
112+ className = "asset-table__action-option"
113+ >
114+ Open in New Tab
115+ </ Link >
116+ </ li >
117+ </ ul > }
118+ </ td >
119+ </ tr >
120+ ) ;
121+ }
122+ }
123+
124+ AssetListRowBase . propTypes = {
125+ asset : PropTypes . shape ( {
126+ key : PropTypes . string . isRequired ,
127+ url : PropTypes . string . isRequired ,
128+ sketchId : PropTypes . string ,
129+ sketchName : PropTypes . string ,
130+ name : PropTypes . string . isRequired ,
131+ size : PropTypes . number . isRequired
132+ } ) . isRequired ,
133+ deleteAssetRequest : PropTypes . func . isRequired ,
134+ username : PropTypes . string . isRequired
135+ } ;
136+
137+ function mapStateToPropsAssetListRow ( state ) {
138+ return {
139+ username : state . user . username
140+ } ;
141+ }
142+
143+ function mapDispatchToPropsAssetListRow ( dispatch ) {
144+ return bindActionCreators ( AssetActions , dispatch ) ;
145+ }
146+
147+ const AssetListRow = connect ( mapStateToPropsAssetListRow , mapDispatchToPropsAssetListRow ) ( AssetListRowBase ) ;
11148
12149class AssetList extends React . Component {
13150 constructor ( props ) {
@@ -16,10 +153,7 @@ class AssetList extends React.Component {
16153 }
17154
18155 getAssetsTitle ( ) {
19- if ( ! this . props . username || this . props . username === this . props . user . username ) {
20- return 'p5.js Web Editor | My assets' ;
21- }
22- return `p5.js Web Editor | ${ this . props . username } 's assets` ;
156+ return 'p5.js Web Editor | My assets' ;
23157 }
24158
25159 hasAssets ( ) {
@@ -39,7 +173,6 @@ class AssetList extends React.Component {
39173 }
40174
41175 render ( ) {
42- const username = this . props . username !== undefined ? this . props . username : this . props . user . username ;
43176 const { assetList } = this . props ;
44177 return (
45178 < div className = "asset-table-container" >
@@ -52,24 +185,14 @@ class AssetList extends React.Component {
52185 < table className = "asset-table" >
53186 < thead >
54187 < tr >
55- < th scope = "col" > Name</ th >
56- < th scope = "col" > Size</ th >
57- < th scope = "col" > Sketch</ th >
188+ < th > Name</ th >
189+ < th > Size</ th >
190+ < th > Sketch</ th >
191+ < th scope = "col" > </ th >
58192 </ tr >
59193 </ thead >
60194 < tbody >
61- { assetList . map ( asset =>
62- (
63- < tr className = "asset-table__row" key = { asset . key } >
64- < th scope = "row" >
65- < Link to = { asset . url } target = "_blank" >
66- { asset . name }
67- </ Link >
68- </ th >
69- < td > { prettyBytes ( asset . size ) } </ td >
70- < td > < Link to = { `/${ username } /sketches/${ asset . sketchId } ` } > { asset . sketchName } </ Link > </ td >
71- </ tr >
72- ) ) }
195+ { assetList . map ( asset => < AssetListRow asset = { asset } key = { asset . key } /> ) }
73196 </ tbody >
74197 </ table > }
75198 </ div >
@@ -81,7 +204,6 @@ AssetList.propTypes = {
81204 user : PropTypes . shape ( {
82205 username : PropTypes . string
83206 } ) . isRequired ,
84- username : PropTypes . string . isRequired ,
85207 assetList : PropTypes . arrayOf ( PropTypes . shape ( {
86208 key : PropTypes . string . isRequired ,
87209 name : PropTypes . string . isRequired ,
@@ -97,7 +219,6 @@ function mapStateToProps(state) {
97219 return {
98220 user : state . user ,
99221 assetList : state . assets . list ,
100- totalSize : state . assets . totalSize ,
101222 loading : state . loading
102223 } ;
103224}
0 commit comments