| 1 |
/** |
| 2 |
* Reset course progress. |
| 3 |
* |
| 4 |
* @since 4.0.5. |
| 5 |
* @author Nhamdv - Code choi choi in Physcode. |
| 6 |
*/ |
| 7 |
const { __ } = wp.i18n; |
| 8 |
const { TextControl, Button, Spinner, CheckboxControl, Notice } = wp.components; |
| 9 |
const { useState, useEffect } = wp.element; |
| 10 |
const { addQueryArgs } = wp.url; |
| 11 |
|
| 12 |
const ResetCourse = () => { |
| 13 |
const [ loading, setLoading ] = useState( false ); |
| 14 |
const [ search, setSearch ] = useState( '' ); |
| 15 |
const [ data, setData ] = useState( [] ); |
| 16 |
const [ checkData, setCheckData ] = useState( [] ); |
| 17 |
const [ message, setMessage ] = useState( [] ); |
| 18 |
const [ loadingReset, setLoadingReset ] = useState( false ); |
| 19 |
|
| 20 |
useEffect( () => { |
| 21 |
responsiveData( search ); |
| 22 |
}, [ search ] ); |
| 23 |
|
| 24 |
const responsiveData = async ( s ) => { |
| 25 |
try { |
| 26 |
if ( ! s || loading ) { |
| 27 |
setMessage( [] ); |
| 28 |
setData( [] ); |
| 29 |
return; |
| 30 |
} |
| 31 |
|
| 32 |
if ( s.length < 3 ) { |
| 33 |
setMessage( [ { status: 'error', message: 'Please enter at least 3 characters to searching course.' } ] ); |
| 34 |
setData( [] ); |
| 35 |
return; |
| 36 |
} |
| 37 |
|
| 38 |
setLoading( true ); |
| 39 |
|
| 40 |
const response = await wp.apiFetch( { |
| 41 |
path: addQueryArgs( 'lp/v1/admin/tools/reset-data/search-courses', { |
| 42 |
s, |
| 43 |
} ), |
| 44 |
method: 'GET', |
| 45 |
} ); |
| 46 |
|
| 47 |
const { status, data } = response; |
| 48 |
|
| 49 |
setLoading( false ); |
| 50 |
|
| 51 |
if ( status === 'success' ) { |
| 52 |
setData( data ); |
| 53 |
setMessage( [] ); |
| 54 |
} else { |
| 55 |
setMessage( [ { status: 'error', message: response.message || 'LearnPress: Search Course Fail!' } ] ); |
| 56 |
setData( [] ); |
| 57 |
} |
| 58 |
} catch ( error ) { |
| 59 |
console.log( error.message ); |
| 60 |
} |
| 61 |
}; |
| 62 |
|
| 63 |
function checkItems( id ) { |
| 64 |
const datas = [ ...checkData ]; |
| 65 |
|
| 66 |
if ( datas.includes( id ) ) { |
| 67 |
const index = datas.indexOf( id ); |
| 68 |
|
| 69 |
if ( index > -1 ) { |
| 70 |
datas.splice( index, 1 ); |
| 71 |
} |
| 72 |
} else { |
| 73 |
datas.push( id ); |
| 74 |
} |
| 75 |
|
| 76 |
setCheckData( datas ); |
| 77 |
} |
| 78 |
|
| 79 |
const resetCourse = async () => { |
| 80 |
if ( checkData.length === 0 ) { |
| 81 |
setMessage( [ { status: 'error', message: 'Please chooce Course for reset data!' } ] ); |
| 82 |
return; |
| 83 |
} |
| 84 |
|
| 85 |
// eslint-disable-next-line no-alert |
| 86 |
if ( ! confirm( 'Are you sure to reset course progress of all users enrolled this course?' ) ) { |
| 87 |
return; |
| 88 |
} |
| 89 |
|
| 90 |
const notice = []; |
| 91 |
|
| 92 |
try { |
| 93 |
setLoadingReset( true ); |
| 94 |
|
| 95 |
for ( const courseId of checkData ) { |
| 96 |
const response = await wp.apiFetch( { |
| 97 |
path: addQueryArgs( 'lp/v1/admin/tools/reset-data/reset-courses', { |
| 98 |
courseId, |
| 99 |
} ), |
| 100 |
method: 'GET', |
| 101 |
} ); |
| 102 |
|
| 103 |
const { status, data, message } = response; |
| 104 |
|
| 105 |
notice.push( { status, message: message || `Course #${ courseId } reset successfully!` } ); |
| 106 |
} |
| 107 |
|
| 108 |
setLoadingReset( false ); |
| 109 |
} catch ( error ) { |
| 110 |
notice.push( { status: 'error', message: error.message || `LearnPress Error: Reset Course Data.` } ); |
| 111 |
} |
| 112 |
|
| 113 |
setMessage( notice ); |
| 114 |
}; |
| 115 |
|
| 116 |
return ( |
| 117 |
<> |
| 118 |
<h2>{ __( 'Reset Course Progress', 'learnpress' ) }</h2> |
| 119 |
<div className="description"> |
| 120 |
<p>{ __( 'This action will reset course progress of all users who have enrolled.', 'learnpress' ) }</p> |
| 121 |
<p>{ __( 'Search results only show if courses have user data.', 'learnpress' ) }</p> |
| 122 |
<div> |
| 123 |
<TextControl |
| 124 |
placeholder={ __( 'Search course by name', 'learnpress' ) } |
| 125 |
value={ search } |
| 126 |
onChange={ ( value ) => setSearch( value ) } |
| 127 |
style={ { width: 300 } } |
| 128 |
/> |
| 129 |
</div> |
| 130 |
</div> |
| 131 |
|
| 132 |
{ loading && <Spinner /> } |
| 133 |
|
| 134 |
{ data.length > 0 && ( |
| 135 |
<> |
| 136 |
<div className="lp-reset-course_progress" style={ { |
| 137 |
border: '1px solid #eee', |
| 138 |
} }> |
| 139 |
<div> |
| 140 |
<div style={ { background: '#eee' } }> |
| 141 |
<div> |
| 142 |
<CheckboxControl |
| 143 |
checked={ checkData.length === data.length } |
| 144 |
onChange={ () => { |
| 145 |
if ( checkData.length === data.length ) { |
| 146 |
setCheckData( [] ); |
| 147 |
} else { |
| 148 |
setCheckData( data.map( ( dt ) => dt.id ) ); |
| 149 |
} |
| 150 |
} } |
| 151 |
style={ { margin: 0 } } |
| 152 |
/> |
| 153 |
</div> |
| 154 |
<div>{ __( 'ID', 'learnpress' ) }</div> |
| 155 |
<div>{ __( 'Name', 'learnpress' ) }</div> |
| 156 |
<div>{ __( 'Students', 'learnpress' ) }</div> |
| 157 |
</div> |
| 158 |
</div> |
| 159 |
|
| 160 |
<div style={ { height: '100%', maxHeight: 200, overflow: 'auto' } }> |
| 161 |
{ data.map( ( dt ) => { |
| 162 |
return ( |
| 163 |
<div style={ { borderTop: '1px solid #eee' } } key={ dt.id }> |
| 164 |
<div> |
| 165 |
<CheckboxControl |
| 166 |
checked={ checkData.includes( dt.id ) } |
| 167 |
onChange={ () => checkItems( dt.id ) } |
| 168 |
/> |
| 169 |
</div> |
| 170 |
<div>#{ dt.id }</div> |
| 171 |
<div>{ dt.title }</div> |
| 172 |
<div>{ dt.students }</div> |
| 173 |
</div> |
| 174 |
); |
| 175 |
} ) } |
| 176 |
</div> |
| 177 |
</div> |
| 178 |
|
| 179 |
{ loadingReset ? <Spinner /> : ( |
| 180 |
<Button |
| 181 |
isPrimary |
| 182 |
onClick={ () => resetCourse() } |
| 183 |
style={ { marginTop: 10, height: 30 } } |
| 184 |
> |
| 185 |
{ __( 'Reset now', 'learnpress' ) } |
| 186 |
</Button> |
| 187 |
) } |
| 188 |
</> |
| 189 |
) } |
| 190 |
|
| 191 |
{ message.length > 0 && message.map( ( mess, index ) => { |
| 192 |
return ( |
| 193 |
<Notice status={ mess.status } key={ index } isDismissible={ false }> |
| 194 |
{ mess.message } |
| 195 |
</Notice> |
| 196 |
); |
| 197 |
} ) } |
| 198 |
|
| 199 |
<style> |
| 200 |
{ '\ |
| 201 |
.lp-reset-course_progress .components-base-control__field {\ |
| 202 |
margin: 0;\ |
| 203 |
}\ |
| 204 |
.components-notice{\ |
| 205 |
margin-left: 0;\ |
| 206 |
}\ |
| 207 |
.lp-reset-course_progress > div > div{\ |
| 208 |
display: grid;\ |
| 209 |
grid-template-columns: 80px 50px 1fr 80px;\ |
| 210 |
align-items: center;\ |
| 211 |
}\ |
| 212 |
.lp-reset-course_progress > div > div > div{\ |
| 213 |
maegin: 0;\ |
| 214 |
padding: 8px 10px;\ |
| 215 |
}\ |
| 216 |
' } |
| 217 |
|
| 218 |
</style> |
| 219 |
</> |
| 220 |
); |
| 221 |
}; |
| 222 |
export default ResetCourse; |
| 223 |
|