1- import React , { useState } from "react"
1+ import React , { useEffect , useState } from "react"
22import * as CONST from "./constants"
33import Card from "react-bootstrap/Card"
4- import Button from 'react-bootstrap/Button'
54import { useNavigate , useParams } from "react-router-dom"
65import { WOQLClientObj } from "../init-woql-client"
7- import Form from "react-bootstrap/Form"
86import Stack from "react-bootstrap/Stack"
9- import { status , extractID } from "./utils"
7+ import { status } from "./utils"
108import { ChangeRequest } from "../hooks/ChangeRequest"
11- import Spinner from 'react-bootstrap/Spinner' ;
12-
13- const ActionButton = ( { variant, title, content, onClick, loading, icon} ) => {
14- return < Button
15- className = "text-dark btn btn-sm fw-bold d-flex mt-3 float-end"
16- variant = { variant }
17- title = { title }
18- onClick = { onClick } >
19- { loading && < Spinner
20- as = "span"
21- animation = "border"
22- size = "sm"
23- role = "status"
24- className = "mr-1 mt-1"
25- aria-hidden = "true"
26- /> }
27- < div className = "d-flex" >
28- { icon }
29- < label > { content } </ label >
30- </ div >
31- </ Button >
32- }
33-
34- /**
35- * @returns buttons to reject commit or approve based on user action
36- */
37- const Actions = ( { checked, message, setKey, setMessage} ) => {
38-
39- const {
40- currentCRObject,
41- setCurrentCRObject,
42- exitChangeRequestBranch
43- } = WOQLClientObj ( )
44-
45- const {
46- updateChangeRequestStatus,
47- getChangeRequestList,
48- loading
49- } = ChangeRequest ( )
50-
51- const { organization, dataProduct, id} = useParams ( )
52- const navigate = useNavigate ( ) // to navigate
53-
54- /** handle Message */
55- async function handleMessage ( ) {
56- let id = extractID ( currentCRObject [ "@id" ] )
57- // this call return the changeRequestObj Updated
58- let res = await updateChangeRequestStatus ( message , currentCRObject . status , id )
59- // we'll see if add need rebase check every time
60- res . needRebase = currentCRObject . needRebase
61- setCurrentCRObject ( res )
62- if ( setKey ) setKey ( CONST . MESSAGES )
63- if ( setMessage ) setMessage ( "" )
64- }
65-
66- /** handle Merge */
67- async function handleMerge ( ) {
68- let res = await updateChangeRequestStatus ( message , CONST . MERGED , id )
69- if ( res ) {
70- setCurrentCRObject ( false )
71- exitChangeRequestBranch ( )
72- navigate ( `/${ organization } /${ dataProduct } ` )
73- }
74- }
75-
76- /** handle Reject */
77- async function handleReject ( ) {
78- let res = await updateChangeRequestStatus ( message , CONST . REJECTED , id )
79- if ( res ) {
80- setCurrentCRObject ( false )
81- exitChangeRequestBranch ( )
82- navigate ( `/${ organization } /${ dataProduct } ` )
83- }
84- }
85-
86- let chosen = CONST . REVIEW_OPTIONS . filter ( arr => arr . title === checked )
87-
88- if ( checked === CONST . APPROVE ) {
89- return < ActionButton variant = "success"
90- loading = { loading }
91- title = { "Approve Changes" }
92- content = { checked }
93- icon = { chosen [ 0 ] . icon }
94- onClick = { handleMerge } />
95- }
96- else if ( checked === CONST . COMMENT ) {
97- return < ActionButton variant = "light"
98- title = { "Leave a Comment or message" }
99- content = { checked }
100- loading = { loading }
101- icon = { chosen [ 0 ] . icon }
102- onClick = { handleMessage } />
103- }
104- else if ( checked === CONST . REJECT ) {
105- return < ActionButton variant = "danger"
106- title = { "Reject Changes" }
107- content = { checked }
108- loading = { loading }
109- icon = { chosen [ 0 ] . icon }
110- onClick = { handleReject } />
111- }
112- return < div />
113- }
114-
115- /**
116- * @returns help texts
117- */
118- function getHelpText ( checked ) {
119- const arr = CONST . REVIEW_OPTIONS . filter ( arr => arr . title === checked )
120- if ( ! arr ) return < div />
121- return < small className = "fw-light" > { arr [ 0 ] . helpText } </ small >
122- }
123-
124- function getChecked ( checked , id ) {
125- return checked === id ? true : false
9+ import ButtonGroup from 'react-bootstrap/ButtonGroup' ;
10+ import ToggleButton from 'react-bootstrap/ToggleButton' ;
11+ import { Loading } from "../components/Loading"
12+ import { MessageBox , MessageComponent } from "./Messages"
13+ import { AiOutlineCheck , AiOutlineClose } from "react-icons/ai"
14+
15+ const ToggleActions = ( { message } ) => {
16+ const [ action , setAction ] = useState ( false ) ;
17+ const { setCurrentCRObject, exitChangeRequestBranch } = WOQLClientObj ( )
18+ const { updateChangeRequestStatus, loading } = ChangeRequest ( )
19+ const { organization, dataProduct , id} = useParams ( )
20+ const navigate = useNavigate ( )
21+
22+
23+ useEffect ( ( ) => {
24+ async function doAction ( ) {
25+ let status = action === CONST . APPROVE ? CONST . MERGED : CONST . REJECTED
26+ let res = await updateChangeRequestStatus ( message , status , id )
27+ if ( res ) {
28+ setCurrentCRObject ( false )
29+ exitChangeRequestBranch ( )
30+ navigate ( `/${ organization } /${ dataProduct } ` )
31+ }
32+ }
33+ if ( action ) doAction ( )
34+ } , [ action ] )
35+
36+ const reviewButtons = [
37+ { name : CONST . APPROVE , value : CONST . APPROVE , className : "rounded-left" , variant : "outline-success" , icon : < AiOutlineCheck className = "mr-1 mb-1 text-success" /> } ,
38+ { name : CONST . REJECT , value : CONST . REJECT , className : "rounded-right" , variant : "outline-danger" , icon : < AiOutlineClose className = "mr-1 mb-1 text-danger" /> }
39+ ] ;
40+
41+ if ( loading ) return < Loading message = { action === CONST . APPROVE ? `Approving Change Request ...` : `Rejecting Change Request ...` } />
42+
43+ return < Stack directtion = "horizontal" className = "float-right" >
44+ < small className = "text-muted fst-italic fw-light mr-2 ms-auto" >
45+ { `Approve or Reject Change Request` }
46+ </ small >
47+ < ButtonGroup >
48+ { reviewButtons . map ( ( button ) => (
49+ < ToggleButton
50+ key = { button . name }
51+ id = { button . name }
52+ type = "radio"
53+ variant = { button . variant }
54+ name = { button . name }
55+ value = { button . value }
56+ className = { button . className }
57+ checked = { action === button . value }
58+ onChange = { ( e ) => setAction ( e . currentTarget . value ) }
59+ >
60+ { button . icon } { button . name }
61+ </ ToggleButton >
62+ ) ) }
63+ </ ButtonGroup >
64+ </ Stack >
12665}
12766
128- /**
129- * @returns Check boxes for CR actions
130- */
131- const FormCheck = ( { checked, setChecked} ) => {
132- return CONST . REVIEW_OPTIONS . map ( arr => {
133- let id = arr . title
134- return < >
135- < Form . Check
136- checked = { getChecked ( checked , id ) }
137- onChange = { ( e ) => setChecked ( id ) }
138- className = "mr-4"
139- type = { "radio" }
140- id = { id }
141- label = { arr . title }
142- />
143- </ >
144- } )
145- }
14667
14768/**
14869 * @returns view based on CR actions
14970 */
150- export const Review = ( { message, setMessage, checked , setKey } ) => {
71+ export const Review = ( { message, setMessage } ) => {
15172 return < React . Fragment >
152- < Form . Control as = "textarea"
153- rows = { 5 }
154- value = { message }
155- onChange = { e => setMessage ( e . target . value ) }
156- style = { { color : "white" } }
157- className = "bg-dark border-secondary"
158- placeholder = { "Add a new comment or message ..." } />
159-
160- < Actions checked = { checked } message = { message } setMessage = { setMessage } setKey = { setKey } />
73+ < MessageBox setMessage = { setMessage } message = { message } />
74+ < ToggleActions message = { message } />
16175 </ React . Fragment >
16276}
16377
164- export const ReviewComponent = ( { setKey } ) => {
78+ export const ReviewComponent = ( ) => {
16579 const {
16680 userHasMergeRole,
16781 currentCRObject
16882 } = WOQLClientObj ( )
16983
170- // set default action as COMMENT
171- const [ checked , setChecked ] = useState ( CONST . APPROVE )
17284 // feedback constants
17385 const [ message , setMessage ] = useState ( "" )
17486
17587 if ( ! userHasMergeRole ) {
17688 // for collaborator or reader role
177- return < Review message = { message } setMessage = { setMessage } checked = { checked } />
89+ return < MessageComponent />
17890 }
17991
18092 return < Card className = "bg-transparent border border-dark m-3" >
@@ -186,15 +98,7 @@ export const ReviewComponent = ({setKey}) => {
18698 </ Stack >
18799 </ Card . Header >
188100 < Card . Body >
189-
190- < div className = "d-flex mb-1" >
191- < Stack direction = "horizontal" gap = { 3 } className = "text-right w-100" >
192- < FormCheck checked = { checked } setChecked = { setChecked } />
193- < span className = "text-light ms-auto" > { getHelpText ( checked ) } </ span >
194- </ Stack >
195- </ div >
196-
197- < Review message = { message } setMessage = { setMessage } checked = { checked } setKey = { setKey } />
101+ < Review message = { message } setMessage = { setMessage } />
198102 </ Card . Body >
199103 </ Card >
200104
0 commit comments