@@ -25,6 +25,8 @@ import {
25
25
import qs from 'qs' ;
26
26
import LoginModal from 'components/LoginModal' ;
27
27
import modalStyle from 'components/LoginModal/modal.scss' ;
28
+ import { PrimaryButton } from 'topcoder-react-ui-kit' ;
29
+ import tc from 'components/buttons/themed/tc.scss' ;
28
30
// SVGs and assets
29
31
import GestureIcon from 'assets/images/icon-gesture.svg' ;
30
32
import ReadMoreArrow from 'assets/images/read-more-arrow.svg' ;
@@ -184,19 +186,19 @@ class Article extends React.Component {
184
186
</ div >
185
187
< div className = { theme . bannerInnerRight } >
186
188
{
187
- fields . featuredImage ? (
188
- < div className = { theme [ 'site-header-background' ] } >
189
- < svg className = { theme . bannerSvg } >
190
- < clipPath id = "thrive-banner-clip-path" clipPathUnits = "objectBoundingBox" >
191
- < path d = "M0.477,1 C0.72,0.999,1,0.804,1,0.56 C1,0.316,0.766,-0.067,0.528,0.021 C0.343,0.089,0.145,-0.088,0.076,0.063 C0.016,0.193,-0.071,0.456,0.101,0.618 C0.274,0.782,0.234,1,0.477,1" />
192
- </ clipPath >
193
- </ svg >
194
- < div className = { theme . bannerClippedImageHolder } style = { { backgroundImage : `url(${ subData . assets . items [ fields . featuredImage . sys . id ] . fields . file . url } )` } } />
195
- </ div >
196
- ) : (
197
- < img src = { DEFAULT_BANNER_IMAGE } alt = "Thrive - default banner" className = { theme [ 'site-header-background' ] } />
198
- )
199
- }
189
+ fields . featuredImage ? (
190
+ < div className = { theme [ 'site-header-background' ] } >
191
+ < svg className = { theme . bannerSvg } >
192
+ < clipPath id = "thrive-banner-clip-path" clipPathUnits = "objectBoundingBox" >
193
+ < path d = "M0.477,1 C0.72,0.999,1,0.804,1,0.56 C1,0.316,0.766,-0.067,0.528,0.021 C0.343,0.089,0.145,-0.088,0.076,0.063 C0.016,0.193,-0.071,0.456,0.101,0.618 C0.274,0.782,0.234,1,0.477,1" />
194
+ </ clipPath >
195
+ </ svg >
196
+ < div className = { theme . bannerClippedImageHolder } style = { { backgroundImage : `url(${ subData . assets . items [ fields . featuredImage . sys . id ] . fields . file . url } )` } } />
197
+ </ div >
198
+ ) : (
199
+ < img src = { DEFAULT_BANNER_IMAGE } alt = "Thrive - default banner" className = { theme [ 'site-header-background' ] } />
200
+ )
201
+ }
200
202
</ div >
201
203
</ div >
202
204
< img src = "https://images.ctfassets.net/piwi0eufbb2g/3StLyQh5ne1Lk9H7C1oVxv/52f17a02122212052e44585d3e79fcf7/29320408-E820-48E1-B0FD-539EAC296910.svg" alt = "Thrive banner shape" className = { theme . bannerBottShape } />
@@ -210,37 +212,37 @@ class Article extends React.Component {
210
212
{ /* Authors */ }
211
213
< div className = { theme . authorContainer } >
212
214
{
213
- _ . map ( fields . contentAuthor , author => (
214
- < div key = { author . sys . id } className = { theme . authorWrapper } >
215
- {
216
- subData . entries . items [ author . sys . id ] . fields . avatar ? (
217
- < ContentfulLoader
218
- assetIds = { subData . entries . items [ author . sys . id ] . fields . avatar . sys . id }
219
- preview = { preview }
220
- spaceName = { spaceName }
221
- environment = { environment }
222
- render = { avatarData => (
223
- < img src = { avatarData . assets . items [ subData . entries . items [ author . sys . id ] . fields . avatar . sys . id ] . fields . file . url } alt = "article author avatar" className = { theme . avatar } />
224
- ) }
225
- renderPlaceholder = { LoadingIndicator }
226
- />
227
- ) : null
228
- }
229
- < div className = { theme . authorInfos } >
230
- < span className = { theme . name } >
231
- { subData . entries . items [ author . sys . id ] . fields . name }
232
- </ span >
215
+ _ . map ( fields . contentAuthor , author => (
216
+ < div key = { author . sys . id } className = { theme . authorWrapper } >
233
217
{
234
- subData . entries . items [ author . sys . id ] . fields . tcHandle ? (
235
- < span className = { theme . handle } >
236
- { subData . entries . items [ author . sys . id ] . fields . tcHandle }
237
- </ span >
218
+ subData . entries . items [ author . sys . id ] . fields . avatar ? (
219
+ < ContentfulLoader
220
+ assetIds = { subData . entries . items [ author . sys . id ] . fields . avatar . sys . id }
221
+ preview = { preview }
222
+ spaceName = { spaceName }
223
+ environment = { environment }
224
+ render = { avatarData => (
225
+ < img src = { avatarData . assets . items [ subData . entries . items [ author . sys . id ] . fields . avatar . sys . id ] . fields . file . url } alt = "article author avatar" className = { theme . avatar } />
226
+ ) }
227
+ renderPlaceholder = { LoadingIndicator }
228
+ />
238
229
) : null
239
230
}
231
+ < div className = { theme . authorInfos } >
232
+ < span className = { theme . name } >
233
+ { subData . entries . items [ author . sys . id ] . fields . name }
234
+ </ span >
235
+ {
236
+ subData . entries . items [ author . sys . id ] . fields . tcHandle ? (
237
+ < span className = { theme . handle } >
238
+ { subData . entries . items [ author . sys . id ] . fields . tcHandle }
239
+ </ span >
240
+ ) : null
241
+ }
242
+ </ div >
240
243
</ div >
241
- </ div >
242
- ) )
243
- }
244
+ ) )
245
+ }
244
246
</ div >
245
247
< div className = { theme . separator } />
246
248
< h3 className = { theme . label } > DURATION</ h3 >
@@ -273,12 +275,12 @@ class Article extends React.Component {
273
275
{ /* Tags */ }
274
276
< div className = { theme . tagContainer } >
275
277
{
276
- _ . map ( fields . tags , tag => (
277
- < div className = { theme . tagItem } key = { tag } title = { `Search for articles labelled as ${ tag } ` } >
278
- < Link to = { `${ config . TC_EDU_BASE_PATH } ${ config . TC_EDU_SEARCH_PATH } ?${ qs . stringify ( { tags : tag } ) } ` } key = { `${ tag } ` } > { tag } </ Link >
279
- </ div >
280
- ) )
281
- }
278
+ _ . map ( fields . tags , tag => (
279
+ < div className = { theme . tagItem } key = { tag } title = { `Search for articles labelled as ${ tag } ` } >
280
+ < Link to = { `${ config . TC_EDU_BASE_PATH } ${ config . TC_EDU_SEARCH_PATH } ?${ qs . stringify ( { tags : tag } ) } ` } key = { `${ tag } ` } > { tag } </ Link >
281
+ </ div >
282
+ ) )
283
+ }
282
284
</ div >
283
285
< div className = { theme . separator } />
284
286
< h3 className = { theme . label } > share</ h3 >
@@ -313,10 +315,10 @@ class Article extends React.Component {
313
315
>
314
316
< MarkdownRenderer markdown = { fields . content } { ...contentfulConfig } />
315
317
{
316
- fields . type === 'Video' && fields . contentUrl ? (
317
- < YouTubeVideo src = { fields . contentUrl } />
318
- ) : null
319
- }
318
+ fields . type === 'Video' && fields . contentUrl ? (
319
+ < YouTubeVideo src = { fields . contentUrl } />
320
+ ) : null
321
+ }
320
322
{ /* Voting */ }
321
323
< div className = { theme . actionContainer } >
322
324
< div className = { theme . action } >
@@ -325,8 +327,8 @@ class Article extends React.Component {
325
327
</ div >
326
328
< span >
327
329
{
328
- upvotes
329
- }
330
+ upvotes
331
+ }
330
332
</ span >
331
333
</ div >
332
334
< div className = { theme . action } >
@@ -338,44 +340,52 @@ class Article extends React.Component {
338
340
</ div >
339
341
{ /* Discord */ }
340
342
< div className = { theme . actionContainer } >
341
- < a href = "https://discord.gg/topcoder?ref=thrive-article" rel = "noopener noreferrer" target = "_blank" > < DiscordIconWhite /> Chat on Discord</ a >
343
+ < PrimaryButton
344
+ to = "https://discord.gg/topcoder?ref=thrive-article"
345
+ openNewTab
346
+ theme = { {
347
+ button : tc [ 'primary-green-md' ] ,
348
+ } }
349
+ >
350
+ < DiscordIconWhite /> Chat on Discord
351
+ </ PrimaryButton >
342
352
</ div >
343
353
</ div >
344
354
</ div >
345
355
{ /* Recommended */ }
346
356
{
347
- fields . recommended ? (
348
- < div className = { theme . recommendedContainer } >
349
- < div className = { theme . recommendedTopShape } />
350
- < h3 className = { theme . recommendedTitle } > Recommended for you</ h3 >
351
- < div className = { theme . recommended } >
352
- {
353
- _ . map ( fields . recommended , rec => (
354
- < div key = { rec . sys . id } className = { theme . recommendedCard } >
355
- {
356
- subData . entries . items [ rec . sys . id ] . fields . featuredImage ? (
357
- < ContentfulLoader
358
- assetIds = { subData . entries . items [ rec . sys . id ] . fields . featuredImage . sys . id }
359
- preview = { preview }
360
- spaceName = { spaceName }
361
- environment = { environment }
362
- render = { imageData => (
363
- < React . Fragment >
364
- < div
365
- style = { { backgroundImage : `url(${ imageData . assets . items [ subData . entries . items [ rec . sys . id ] . fields . featuredImage . sys . id ] . fields . file . url } )` } }
366
- className = { theme . recommendedImage }
367
- />
368
- < div className = { theme . recommendedImageBottomShape } />
369
- </ React . Fragment >
370
- ) }
371
- renderPlaceholder = { LoadingIndicator }
372
- />
373
- ) : null
374
- }
375
- < h3 className = { theme . recommendedCardTitle } >
357
+ fields . recommended ? (
358
+ < div className = { theme . recommendedContainer } >
359
+ < div className = { theme . recommendedTopShape } />
360
+ < h3 className = { theme . recommendedTitle } > Recommended for you</ h3 >
361
+ < div className = { theme . recommended } >
362
+ {
363
+ _ . map ( fields . recommended , rec => (
364
+ < div key = { rec . sys . id } className = { theme . recommendedCard } >
376
365
{
377
- subData . entries . items [ rec . sys . id ] . fields . externalArticle
378
- && subData . entries . items [ rec . sys . id ] . fields . contentUrl ? (
366
+ subData . entries . items [ rec . sys . id ] . fields . featuredImage ? (
367
+ < ContentfulLoader
368
+ assetIds = { subData . entries . items [ rec . sys . id ] . fields . featuredImage . sys . id }
369
+ preview = { preview }
370
+ spaceName = { spaceName }
371
+ environment = { environment }
372
+ render = { imageData => (
373
+ < React . Fragment >
374
+ < div
375
+ style = { { backgroundImage : `url(${ imageData . assets . items [ subData . entries . items [ rec . sys . id ] . fields . featuredImage . sys . id ] . fields . file . url } )` } }
376
+ className = { theme . recommendedImage }
377
+ />
378
+ < div className = { theme . recommendedImageBottomShape } />
379
+ </ React . Fragment >
380
+ ) }
381
+ renderPlaceholder = { LoadingIndicator }
382
+ />
383
+ ) : null
384
+ }
385
+ < h3 className = { theme . recommendedCardTitle } >
386
+ {
387
+ subData . entries . items [ rec . sys . id ] . fields . externalArticle
388
+ && subData . entries . items [ rec . sys . id ] . fields . contentUrl ? (
379
389
< a href = { subData . entries . items [ rec . sys . id ] . fields . contentUrl } target = "_blank" rel = "noopener noreferrer" >
380
390
{ subData . entries . items [ rec . sys . id ] . fields . title }
381
391
</ a >
@@ -384,26 +394,26 @@ class Article extends React.Component {
384
394
{ subData . entries . items [ rec . sys . id ] . fields . title }
385
395
</ Link >
386
396
)
387
- }
388
- </ h3 >
389
- < div className = { theme . recommendedCardContent } >
397
+ }
398
+ </ h3 >
399
+ < div className = { theme . recommendedCardContent } >
400
+ {
401
+ `${ htmlToText . fromString (
402
+ ReactDOMServer . renderToString ( markdown (
403
+ subData . entries . items [ rec . sys . id ] . fields . content ,
404
+ ) ) ,
405
+ {
406
+ ignoreHref : true ,
407
+ ignoreImage : true ,
408
+ singleNewLineParagraphs : true ,
409
+ uppercaseHeadings : false ,
410
+ } ,
411
+ ) . substring ( 0 , CONTENT_PREVIEW_LENGTH ) } ...`
412
+ }
413
+ </ div >
390
414
{
391
- `${ htmlToText . fromString (
392
- ReactDOMServer . renderToString ( markdown (
393
- subData . entries . items [ rec . sys . id ] . fields . content ,
394
- ) ) ,
395
- {
396
- ignoreHref : true ,
397
- ignoreImage : true ,
398
- singleNewLineParagraphs : true ,
399
- uppercaseHeadings : false ,
400
- } ,
401
- ) . substring ( 0 , CONTENT_PREVIEW_LENGTH ) } ...`
402
- }
403
- </ div >
404
- {
405
- subData . entries . items [ rec . sys . id ] . fields . externalArticle
406
- && subData . entries . items [ rec . sys . id ] . fields . contentUrl ? (
415
+ subData . entries . items [ rec . sys . id ] . fields . externalArticle
416
+ && subData . entries . items [ rec . sys . id ] . fields . contentUrl ? (
407
417
< a href = { subData . entries . items [ rec . sys . id ] . fields . contentUrl } target = "_blank" rel = "noopener noreferrer" className = { theme . readMore } >
408
418
Read More < ReadMoreArrow />
409
419
</ a >
@@ -412,26 +422,26 @@ class Article extends React.Component {
412
422
Read More < ReadMoreArrow />
413
423
</ Link >
414
424
)
415
- }
416
- </ div >
417
- ) )
418
- }
425
+ }
426
+ </ div >
427
+ ) )
428
+ }
429
+ </ div >
419
430
</ div >
420
- </ div >
421
- ) : null
422
- }
431
+ ) : null
432
+ }
423
433
</ div >
424
434
{
425
435
showLogin && (
426
- < LoginModal
427
- // eslint-disable-next-line no-restricted-globals
428
- retUrl = { isomorphy . isClientSide ( ) ? location . href : null }
429
- onCancel = { ( ) => this . setState ( { showLogin : false } ) }
430
- modalTitle = "Want to vote?"
431
- modalText = "You must be a Topcoder member to do that."
432
- utmSource = "thrive_article"
433
- infoNode = { < p className = { modalStyle . regTxt } > Discover < a href = "/community/learn" target = "_blank" rel = "noreferrer" > other features</ a > you can access by becoming a member.</ p > }
434
- />
436
+ < LoginModal
437
+ // eslint-disable-next-line no-restricted-globals
438
+ retUrl = { isomorphy . isClientSide ( ) ? location . href : null }
439
+ onCancel = { ( ) => this . setState ( { showLogin : false } ) }
440
+ modalTitle = "Want to vote?"
441
+ modalText = "You must be a Topcoder member to do that."
442
+ utmSource = "thrive_article"
443
+ infoNode = { < p className = { modalStyle . regTxt } > Discover < a href = "/community/learn" target = "_blank" rel = "noreferrer" > other features</ a > you can access by becoming a member.</ p > }
444
+ />
435
445
)
436
446
}
437
447
</ React . Fragment >
0 commit comments