1
- import django from 'django'
2
1
import React , { useState , useEffect } from 'react'
2
+ import ReactDOM from 'react-dom'
3
+ import django from 'django'
3
4
import Alert from '../../../static/Alert'
4
-
5
5
import api from '../../../static/api'
6
6
import config from '../../../static/config'
7
7
@@ -18,73 +18,105 @@ const translated = {
18
18
following : django . gettext ( 'Following' )
19
19
}
20
20
21
- export const FollowButton = ( props ) => {
21
+ export const FollowButton = ( {
22
+ project,
23
+ authenticatedAs,
24
+ customClasses = '' ,
25
+ alertTarget = null
26
+ } ) => {
22
27
const [ following , setFollowing ] = useState ( null )
23
28
const [ alert , setAlert ] = useState ( null )
24
29
25
30
const followBtnText = following ? translated . following : translated . follow
26
-
27
31
const followDescriptionText = following
28
32
? translated . followingDescription
29
33
: translated . followDescription
30
34
31
- const followAlertText = following
32
- ? translated . followingAlert
33
- : translated . followAlert
34
-
35
35
useEffect ( ( ) => {
36
- if ( props . authenticatedAs ) {
36
+ if ( authenticatedAs ) {
37
37
api . follow
38
- . get ( props . project )
38
+ . get ( project )
39
39
. done ( ( follow ) => {
40
40
setFollowing ( follow . enabled )
41
- setAlert ( follow . alert )
42
41
} )
43
42
. fail ( ( response ) => {
44
43
if ( response . status === 404 ) {
45
44
setFollowing ( false )
46
45
}
47
46
} )
48
47
}
49
- } , [ props . project , props . authenticatedAs ] )
48
+ } , [ project , authenticatedAs ] )
50
49
51
50
const removeAlert = ( ) => {
52
51
setAlert ( null )
53
52
}
54
53
55
54
const toggleFollow = ( ) => {
56
- if ( props . authenticatedAs === null ) {
55
+ if ( authenticatedAs === null ) {
57
56
window . location . href = config . getLoginUrl ( )
58
57
return
59
58
}
60
- api . follow . change ( { enabled : ! following } , props . project ) . done ( ( follow ) => {
59
+
60
+ api . follow . change ( { enabled : ! following } , project ) . done ( ( follow ) => {
61
61
setFollowing ( follow . enabled )
62
62
setAlert ( {
63
- type : 'success' ,
64
- message : followAlertText
63
+ type : follow . enabled ? 'success' : 'warning ',
64
+ message : follow . enabled ? translated . followAlert : translated . followingAlert
65
65
} )
66
66
} )
67
67
}
68
68
69
+ const buttonClasses = following ? 'a4-btn a4-btn--following' : 'a4-btn a4-btn--follow'
70
+
71
+ const AlertPortal = ( ) => {
72
+ if ( ! alert ) return null
73
+
74
+ if ( ! alertTarget ) {
75
+ console . error ( 'AlertPortal: No alert target provided' )
76
+ return null
77
+ }
78
+
79
+ const container = document . getElementById ( alertTarget )
80
+
81
+ if ( ! container ) {
82
+ console . error ( 'AlertPortal: Target element with ID "' + alertTarget + '" not found in DOM' )
83
+ return null
84
+ }
85
+
86
+ return ReactDOM . createPortal (
87
+ < Alert onClick = { removeAlert } { ...alert } /> ,
88
+ container
89
+ )
90
+ }
91
+
69
92
return (
70
- < span className = " a4-follow" >
93
+ < span className = { ' a4-follow ' + customClasses } >
71
94
< button
72
- className = {
73
- following ? 'a4-btn a4-btn--following' : 'a4-btn a4-btn--follow'
74
- }
95
+ className = { buttonClasses }
75
96
type = "button"
76
97
onClick = { toggleFollow }
77
98
aria-describedby = "follow-description"
78
- disabled = { following === null && props . authenticatedAs !== null }
99
+ aria-pressed = { following }
100
+ disabled = { following === null && authenticatedAs !== null }
79
101
>
80
102
< span className = "a4-follow__btn--content" > { followBtnText } </ span >
103
+
81
104
< span className = "a4-sr-only" id = "follow-description" >
82
105
{ followDescriptionText }
83
106
</ span >
84
107
</ button >
85
- < span className = "a4-follow__notification" >
86
- < Alert onClick = { removeAlert } { ...alert } />
87
- </ span >
108
+
109
+ { alertTarget
110
+ ? (
111
+ < AlertPortal />
112
+ )
113
+ : (
114
+ < span className = "a4-follow__notification" >
115
+ < Alert onClick = { removeAlert } { ...alert } />
116
+ </ span >
117
+ ) }
88
118
</ span >
89
119
)
90
120
}
121
+
122
+ export default FollowButton
0 commit comments