@ -34,13 +34,18 @@ function createEmptyQuestion() {
}
/ * *
* @ param { { title : string , defaultOpen ? : boolean , id ? : string , children : import ( 'react' ) . ReactNode } } p
* @ param { { title : string , subtitle ? : string , defaultOpen ? : boolean , id ? : string , children : import ( 'react' ) . ReactNode } } p
* /
function AccSection ( { title , defaultOpen , id , children } ) {
function AccSection ( { title , subtitle , defaultOpen , id , children } ) {
return (
< div className = "cabinet-brick" >
< details className = "cabinet-disclosure" defaultOpen = { defaultOpen } id = { id || undefined } >
< summary className = "cabinet-disclosure__summary font-headline" > { title } < / summary >
< summary className = "cabinet-disclosure__summary" >
< span className = "cabinet-disclosure__summary-text" >
< span className = "cabinet-disclosure__summary-title font-headline" > { title } < / span >
{ subtitle ? < span className = "cabinet-disclosure__summary-sub" > { subtitle } < / span > : null }
< / span >
< / summary >
< div className = "cabinet-disclosure__body" > { children } < / div >
< / details >
< / div >
@ -235,6 +240,16 @@ export default function TestDetail() {
} ) ;
}
function selectAllVisible ( ) {
setAssignSelected ( ( prev ) => {
const next = new Set ( prev ) ;
for ( const p of assignPeople ) {
next . add ( assignPersonKey ( p ) ) ;
}
return next ;
} ) ;
}
async function postAssign ( ) {
const selectedRows = assignPeople . filter ( ( p ) =>
assignSelected . has ( assignPersonKey ( p ) )
@ -657,14 +672,13 @@ export default function TestDetail() {
При сохранении будет создана новая версия теста .
< / div >
) }
{ data && attemptsErr && (
< p className = "error-text" style = { { marginTop : '0.75rem' , marginBottom : 0 } } role = "alert" >
{ attemptsErr }
< / p >
) }
< / div >
< AccSection title = "Метаинформация" defaultOpen >
< AccSection
title = "О тесте"
subtitle = "Название, описание и порог зачёта"
defaultOpen
>
< div className = "draft-block" >
< label className = "form-label" htmlFor = "draft-title" >
Название
@ -702,17 +716,13 @@ export default function TestDetail() {
< / div >
< / AccSection >
< AccSection title = "Содержание" defaultOpen >
< AccSection
title = "Вопросы"
subtitle = "Тексты, варианты и при необходимости загрузка из файла"
defaultOpen
>
< div className = "draft-block" >
< div
className = "surface-card"
style = { {
padding : '1rem 1.1rem' ,
marginBottom : '1.25rem' ,
borderLeft : '3px solid color-mix(in srgb, var(--primary) 45%, transparent)' ,
} }
aria - label = "Параметры генерации теста с ИИ"
>
< div className = "test-detail-ai-panel" aria - label = "Параметры генерации теста с ИИ" >
< p
className = "font-headline"
style = { { fontSize : '0.95rem' , marginTop : 0 , marginBottom : '0.65rem' } }
@ -792,12 +802,7 @@ export default function TestDetail() {
{ draftQuestions . map ( ( q , qi ) => (
< div
key = { q . key }
className = "question-editor-block"
style = { {
borderTop : '1px solid var(--border-subtle, #2a2a2a)' ,
marginTop : '1rem' ,
paddingTop : '1rem' ,
} }
className = { ` question-editor-block ${ qi === 0 ? ' question-editor-block--first' : '' } ` }
>
< div className = "question-editor-block__header" >
< label
@ -848,11 +853,7 @@ export default function TestDetail() {
< / p >
< ul className = "question-options-list" style = { { listStyle : 'none' , padding : 0 , margin : 0 } } >
{ q . options . map ( ( o , oi ) => (
< li
key = { o . key }
className = "question-option-row"
style = { { display : 'flex' , flexWrap : 'wrap' , alignItems : 'center' , gap : 8 , marginBottom : 8 } }
>
< li key = { o . key } className = "question-option-row" >
< input
key = { ` ${ o . key } - ${ q . hasMultipleAnswers ? 'm' : 's' } ` }
className = "question-option-row__mark"
@ -886,8 +887,7 @@ export default function TestDetail() {
aria - label = "Пометить как верный"
/ >
< input
className = "form-input"
style = { { flex : '1 1 200px' } }
className = "form-input question-option-row__text"
value = { o . text }
onChange = { ( e ) => {
const v = e . target . value ;
@ -908,17 +908,25 @@ export default function TestDetail() {
{ q . options . length > 1 && (
< button
type = "button"
className = "btn btn-ghost btn--sm "
className = "question-option-remove "
onClick = { ( ) => removeOption ( qi , oi ) }
title = "Удалить вариант"
aria - label = "Удалить вариант"
>
убрать
< span className = "material-symbols-outlined" aria - hidden >
close
< / span >
< / button >
) }
< / li >
) ) }
< / ul >
< div className = "inline-actions" style = { { marginTop : 4 } } >
< button type = "button" className = "btn btn-ghost btn--sm" onClick = { ( ) => addOption ( qi ) } >
< div className = "question-editor__footer" >
< button
type = "button"
className = "btn btn-ghost btn--sm"
onClick = { ( ) => addOption ( qi ) }
>
+ вариант
< / button >
{ draftQuestions . length > 1 && (
@ -933,11 +941,92 @@ export default function TestDetail() {
< / div >
< / div >
) ) }
< div className = "inline-actions" style = { { marginTop : '0.75rem' } } >
< button type = "button" className = "btn btn-ghost" onClick = { addQuestion } >
< div className = "test-detail-add-question" >
< button
type = "button"
className = "btn btn-ghost question-editor__add-question"
onClick = { addQuestion }
>
+ вопрос
< / button >
< / div >
< div className = "test-detail-subsection test-detail-subsection--import" >
< h3 className = "test-detail-subsection__title" > Документ в вопросы < / h3 >
< p className = "muted test-detail-hint" style = { { marginTop : 0 } } >
PDF , Word или текст — вставьте в черновик вопросов .
< / p >
< div
className = "import-file-row import-file-row--block"
style = { { marginBottom : importPreview || importErr ? '0.5rem' : 0 , marginTop : 0 } }
>
< input
id = "import-test-file"
className = "import-file-input"
type = "file"
accept = ".pdf,.docx,.txt,.md,application/pdf"
onChange = { onImportFile }
disabled = { importBusy }
aria - label = "Выбрать файл для импорта"
/ >
< label
htmlFor = "import-test-file"
className = { ` btn btn-ghost import-file-label ${ importBusy ? ' is-busy' : '' } ` }
style = { importBusy ? { pointerEvents : 'none' } : undefined }
>
{ importBusy ? 'Обработка…' : 'Выбрать файл' }
< / label >
< / div >
{ importErr && (
< p className = "error-text" role = "alert" >
{ importErr }
< / p >
) }
{ importPreview && (
< div className = "draft-block" style = { { marginTop : '0.65rem' , marginBottom : 0 } } >
< p className = "muted" style = { { marginTop : 0 , marginBottom : 0 } } >
{ importPreview . generation ? . message }
< / p >
{ importPreview . generation ? . textPreview && ! importPreview . generation ? . available && (
< pre
className = "form-input"
style = { {
maxHeight : 180 ,
overflow : 'auto' ,
fontSize : 13 ,
marginTop : 8 ,
whiteSpace : 'pre-wrap' ,
} }
>
{ importPreview . generation . textPreview }
{ importPreview . textLength > 4000 ? '…' : '' }
< / pre >
) }
{ importPreview . generation ? . draft && (
< div className = "inline-actions" style = { { marginTop : 8 , marginBottom : 0 } } >
< button
type = "button"
className = "btn btn-ghost"
onClick = { applyGeneratedDraft }
>
Применить сгенерированный черновик
< / button >
< / div >
) }
{ importPreview . extractedText && (
< div className = "inline-actions" style = { { marginTop : 8 , marginBottom : 0 } } >
< button
type = "button"
className = "btn btn-ghost"
onClick = { applyExtractedToQuestion }
>
Вставить в первый вопрос ( до 2000 симв . )
< / button >
< / div >
) }
< / div >
) }
< / div >
< / div >
< / AccSection >
@ -959,295 +1048,276 @@ export default function TestDetail() {
< / p >
) }
< / div >
< AccSection title = "История версий" defaultOpen = { false } >
< ul className = "version-card-list" aria - label = "Список версий теста" >
{ versions . map ( ( r ) => (
< li key = { r . id } className = "surface-card version-card-list__item" >
< div className = "version-card-list__row" >
< div className = "version-card-list__main" >
< div className = "version-card-list__title-line" >
< span className = "font-headline" style = { { fontSize : '1rem' } } >
v { r . version }
< / span >
{ r . is _active && (
< span className = "code-inline" style = { { fontSize : '0.7rem' } } >
текущая
< AccSection
title = "История"
subtitle = "Версии теста и кто проходил"
defaultOpen = { false }
>
< div className = "test-detail-subsection test-detail-subsection--tight" >
< h3 className = "test-detail-subsection__title" > Версии < / h3 >
< ul className = "version-card-list" aria - label = "Список версий теста" >
{ versions . map ( ( r ) => (
< li key = { r . id } className = "surface-card version-card-list__item" >
< div className = "version-card-list__row" >
< div className = "version-card-list__main" >
< div className = "version-card-list__title-line" >
< span className = "font-headline" style = { { fontSize : '1rem' } } >
v { r . version }
< / span >
) }
< / div >
< p className = "muted mono" style = { { margin : '0.4rem 0 0' , fontSize : '0.8rem' } } >
{ fmtDt ( r . created _at ) }
< / p >
< p className = "muted" style = { { margin : '0.2rem 0 0' , fontSize : '0.8rem' } } >
Активна : { r . is _active ? 'да' : 'нет' }
< / p >
< / div >
{ ! r . is _active && (
< button
type = "button"
className = "btn btn-ghost btn--sm version-card-list__action"
onClick = { ( ) => activateVersion ( r . id ) }
>
Сделать активной
< / button >
) }
< / div >
< / li >
) ) }
< / ul >
< / AccSection >
{ attemptsList != null && attemptsList . length > 0 && (
< AccSection title = "Прогоны и разбор" defaultOpen = { false } >
{ attemptsErr && (
< p className = "error-text" role = "alert" >
{ attemptsErr }
< / p >
) }
< ul className = "attempts-card-list" aria - label = "Список прогонов" >
{ attemptsList . map ( ( a ) => {
const when = a . completedAt
? fmtDt ( a . completedAt )
: a . startedAt
? fmtDt ( a . startedAt )
: '—' ;
const result =
a . status === 'completed' && a . totalQuestions != null ? (
< >
{ a . correctCount } / { a . totalQuestions }
{ a . passed ? ' · зачёт' : ' · незачёт' }
< / >
) : (
a . status
) ;
return (
< li key = { a . id } className = "surface-card attempts-card-list__item" >
< div className = "attempts-card-list__row" >
< div className = "attempts-card-list__main" >
< p className = "muted attempts-card-list__when mono" style = { { margin : 0 , fontSize : '0.8rem' } } >
{ when }
< / p >
< p className = "attempts-card-list__who" style = { { margin : '0.35rem 0 0' , fontWeight : 600 } } >
{ a . attempterName || '—' }
{ a . attempterLogin && (
< span className = "code-inline" style = { { fontSize : 11 , marginLeft : 6 } } >
{ a . attempterLogin }
< / span >
) }
< / p >
< p className = "muted" style = { { margin : '0.25rem 0 0' , fontSize : '0.85rem' } } >
v { a . testVersion } · { ' ' }
< span className = "attempts-card-list__result" > { result } < / span >
< / p >
{ r . is _active && (
< span className = "code-inline" style = { { fontSize : '0.7rem' } } >
текущая
< / span >
) }
< / div >
{ a . status === 'completed' && (
< Link
to = { ` /tests/ ${ id } /attempts/ ${ a . id } /review ` }
className = "btn btn-ghost btn--sm attempts-card-list__action"
>
Разбор
< / Link >
) }
< p className = "muted mono" style = { { margin : '0.4rem 0 0' , fontSize : '0.8rem' } } >
{ fmtDt ( r . created _at ) }
< / p >
< p className = "muted" style = { { margin : '0.2rem 0 0' , fontSize : '0.8rem' } } >
Активна : { r . is _active ? 'да' : 'нет' }
< / p >
< / div >
< / li >
) ;
} ) }
{ ! r . is _active && (
< button
type = "button"
className = "btn btn-ghost btn--sm version-card-list__action"
onClick = { ( ) => activateVersion ( r . id ) }
>
Сделать активной
< / button >
) }
< / div >
< / li >
) ) }
< / ul >
< / AccSection >
) }
< AccSection title = "Публикация (видимость в списке)" defaultOpen = { false } >
< div
className = "inline-actions inline-actions--block-mobile"
style = { { marginTop : '0.5rem' } }
>
{ test ? . chainActive !== false ? (
< button
type = "button"
className = "btn btn-ghost"
disabled = { deactivateBusy }
onClick = { ( ) => setChainVisible ( false ) }
>
Скрыть из списка
< / button >
) : (
< button
type = "button"
className = "btn btn-ghost"
disabled = { deactivateBusy }
onClick = { ( ) => setChainVisible ( true ) }
>
Снова показать в списке
< / button >
< / div >
{ attemptsList !== undefined && (
< div className = "test-detail-subsection" >
< h3 className = "test-detail-subsection__title" > Прохождения < / h3 >
{ attemptsList == null && (
< p
className = { attemptsErr ? 'error-text' : 'text-muted' }
style = { { margin : 0 } }
role = { attemptsErr ? 'alert' : undefined }
>
{ attemptsErr || 'Список прогонов сейчас недоступен.' }
< / p >
) }
{ attemptsList && attemptsList . length > 0 && (
< ul className = "attempts-card-list" aria - label = "Список прогонов" >
{ attemptsList . map ( ( a ) => {
const when = a . completedAt
? fmtDt ( a . completedAt )
: a . startedAt
? fmtDt ( a . startedAt )
: '—' ;
const result =
a . status === 'completed' && a . totalQuestions != null ? (
< >
{ a . correctCount } / { a . totalQuestions }
{ a . passed ? ' · зачёт' : ' · незачёт' }
< / >
) : (
a . status
) ;
return (
< li key = { a . id } className = "surface-card attempts-card-list__item" >
< div className = "attempts-card-list__row" >
< div className = "attempts-card-list__main" >
< p
className = "muted attempts-card-list__when mono"
style = { { margin : 0 , fontSize : '0.8rem' } }
>
{ when }
< / p >
< p
className = "attempts-card-list__who"
style = { { margin : '0.35rem 0 0' , fontWeight : 600 } }
>
{ a . attempterName || '—' }
{ a . attempterLogin && (
< span className = "code-inline" style = { { fontSize : 11 , marginLeft : 6 } } >
{ a . attempterLogin }
< / span >
) }
< / p >
< p className = "muted" style = { { margin : '0.25rem 0 0' , fontSize : '0.85rem' } } >
v { a . testVersion } · { ' ' }
< span className = "attempts-card-list__result" > { result } < / span >
< / p >
< / div >
{ a . status === 'completed' && (
< Link
to = { ` /tests/ ${ id } /attempts/ ${ a . id } /review ` }
className = "btn btn-ghost btn--sm attempts-card-list__action"
>
Разбор
< / Link >
) }
< / div >
< / li >
) ;
} ) }
< / ul >
) }
{ attemptsList && attemptsList . length === 0 && (
< p className = "text-muted" style = { { margin : 0 } } >
Пока нет зарегистрированных прогонов .
< / p >
) }
< / div >
) }
< / div >
< / AccSection >
< AccSection title = "Импорт из файла" defaultOpen = { false } >
< div className = "import-file-row" style = { { marginBottom : '0.5rem' } } >
< input
id = "import-test-file"
className = "import-file-input"
type = "file"
accept = ".pdf,.docx,.txt,.md,application/pdf"
onChange = { onImportFile }
disabled = { importBusy }
aria - label = "Выбрать файл для импорта"
/ >
< label
htmlFor = "import-test-file"
className = { ` btn btn-ghost import-file-label ${ importBusy ? ' is-busy' : '' } ` }
style = { importBusy ? { pointerEvents : 'none' } : undefined }
>
{ importBusy ? 'Обработка…' : 'Выбрать файл' }
< / label >
< / div >
{ importErr && (
< p className = "error-text" role = "alert" >
{ importErr }
< / p >
) }
{ importPreview && (
< div className = "draft-block" style = { { marginBottom : '1rem' } } >
< p className = "muted" style = { { marginTop : 0 } } >
{ importPreview . generation ? . message }
< AccSection
title = "Показ в каталоге"
subtitle = {
assignmentUi && data
? 'Видимость в списке и выдача сотрудникам'
: 'Показать или скрыть в общем списке'
}
defaultOpen = { false }
>
< div className = "test-detail-subsection test-detail-subsection--tight" >
< h3 className = "test-detail-subsection__title" > Видимость < / h3 >
< p className = "test-detail-hint" style = { { marginTop : 0 } } >
Скрытые тесты в общем списке не показываются ; ссылку на тест по - прежнему можно открыть .
< / p >
{ importPreview . generation ? . textPreview && ! importPreview . generation ? . available && (
< pre
className = "form-input"
style = { {
maxHeight : 180 ,
overflow : 'auto' ,
fontSize : 13 ,
marginTop : 8 ,
whiteSpace : 'pre-wrap' ,
} }
>
{ importPreview . generation . textPreview }
{ importPreview . textLength > 4000 ? '…' : '' }
< / pre >
) }
{ importPreview . generation ? . draft && (
< div className = "inline-actions" style = { { marginTop : 8 } } >
< div className = "publication-visibility__actions" style = { { marginTop : 4 } } >
{ test ? . chainActive !== false ? (
< button
type = "button"
className = "btn btn-ghost"
onClick = { applyGeneratedDraft }
disabled = { deactivateBusy }
onClick = { ( ) => setChainVisible ( false ) }
>
Применить сгенерированный черновик
Скрыть из списка
< / button >
< / div >
) }
{ importPreview . extractedText && (
< div className = "inline-actions" style = { { marginTop : 8 } } >
) : (
< button
type = "button"
className = "btn btn-ghost"
onClick = { applyExtractedToQuestion }
disabled = { deactivateBusy }
onClick = { ( ) => setChainVisible ( true ) }
>
Вставить в первый вопрос ( до 2000 симв . )
Снова показать в списке
< / button >
< / div >
) }
) }
< / div >
< / div >
) }
< / AccSection >
{ assignmentUi && data && (
< AccSection title = "Назначение сотрудникам" defaultOpen = { false } >
{ assignErr && (
< p className = "error-text" role = "alert" >
{ assignErr }
{ assignmentUi && data && (
< div className = "test-detail-subsection" >
< h3 className = "test-detail-subsection__title" > Кому выдать < / h3 >
< p className = "test-detail-hint" style = { { marginTop : 0 } } >
Список с учётом поиска и фильтров ; можно отметить всех на экране .
< / p >
) }
< div className = "assign-toolbar" >
< input
type = "search"
className = "form-input assign-toolbar__search"
placeholder = "Поиск: ФИО, логин"
value = { assignSearch }
onChange = { ( e ) => setAssignSearch ( e . target . value ) }
aria - label = "Поиск сотрудника"
/ >
< select
className = "form-input"
value = { assignDept }
onChange = { ( e ) => setAssignDept ( e . target . value ) }
aria - label = "Фильтр по отделу"
>
< option value = "__all__" > Все отделы < / option >
{ assignDepts . map ( ( d ) => (
< option key = { d } value = { d } >
{ d }
< / option >
) ) }
< / select >
< select
className = "form-input"
value = { assignClinic }
onChange = { ( e ) => setAssignClinic ( e . target . value ) }
aria - label = "Кто в модуле"
>
< option value = "all" > Все < / option >
< option value = "with" > С учёткой в модуле < / option >
< option value = "without" > Без учётки ( создать ) < / option >
< / select >
{ assignLoadBusy && < span className = "text-muted" > Загрузка … < / span > }
< / div >
{ assignPeople . length > 0 ? (
< div className = "assign-list" role = "group" aria - label = "Список сотрудников" >
{ assignPeople . map ( ( p ) => {
const k = assignPersonKey ( p ) ;
const picked = assignSelected . has ( k ) ;
return (
< label
key = { k }
className = { ` assign-row ${ picked ? ' assign-row--selected' : '' } ` }
>
< input
type = "checkbox"
checked = { picked }
onChange = { ( ) => toggleAssignPerson ( p ) }
/ >
< span className = "assign-row__text" >
< span className = "assign-row__fio" > { p . fio } < / span >
{ p . webLogin && (
< span className = "assign-row__login" > { p . webLogin } < / span >
) }
< span className = "assign-row__meta" >
{ p . departments || '—' }
{ p . clinicUserId
? ' · есть учётка в модуле'
: ' · нет учётки (создадим при назначении)' }
{ assignErr && (
< p className = "error-text" role = "alert" style = { { marginTop : 0 , marginBottom : 8 } } >
{ assignErr }
< / p >
) }
< div className = "assign-toolbar" >
< input
type = "search"
className = "form-input assign-toolbar__search"
placeholder = "Поиск: ФИО, логин"
value = { assignSearch }
onChange = { ( e ) => setAssignSearch ( e . target . value ) }
aria - label = "Поиск сотрудника"
/ >
< select
className = "form-input"
value = { assignDept }
onChange = { ( e ) => setAssignDept ( e . target . value ) }
aria - label = "Фильтр по отделу"
>
< option value = "__all__" > Все отделы < / option >
{ assignDepts . map ( ( d ) => (
< option key = { d } value = { d } >
{ d }
< / option >
) ) }
< / select >
< select
className = "form-input"
value = { assignClinic }
onChange = { ( e ) => setAssignClinic ( e . target . value ) }
aria - label = "Кто в модуле"
>
< option value = "all" > Все < / option >
< option value = "with" > С учёткой в модуле < / option >
< option value = "without" > Без учётки ( создать ) < / option >
< / select >
{ assignLoadBusy && < span className = "text-muted" > Загрузка … < / span > }
< / div >
{ assignPeople . length > 0 && (
< div
className = "publication-visibility__actions"
style = { { marginTop : '0.45rem' , marginBottom : '0.25rem' } }
>
< button
type = "button"
className = "btn btn-ghost btn--sm"
onClick = { selectAllVisible }
disabled = { assignLoadBusy }
>
Выбрать всех ( { assignPeople . length } )
< / button >
< / div >
) }
{ assignPeople . length > 0 ? (
< div className = "assign-list" role = "group" aria - label = "Список сотрудников" >
{ assignPeople . map ( ( p ) => {
const k = assignPersonKey ( p ) ;
const picked = assignSelected . has ( k ) ;
return (
< label
key = { k }
className = { ` assign-row ${ picked ? ' assign-row--selected' : '' } ` }
>
< input
type = "checkbox"
checked = { picked }
onChange = { ( ) => toggleAssignPerson ( p ) }
/ >
< span className = "assign-row__text" >
< span className = "assign-row__fio" > { p . fio } < / span >
{ p . webLogin && < span className = "assign-row__login" > { p . webLogin } < / span > }
< span className = "assign-row__meta" >
{ p . departments || '—' }
{ p . clinicUserId
? ' · есть учётка в модуле'
: ' · нет учётки (создадим при назначении)' }
< / span >
< / span >
< / span >
< / label >
) ;
} ) }
< / label >
) ;
} ) }
< / div >
) : (
! assignLoadBusy && (
< p className = "text-muted" style = { { margin : '0.5rem 0' } } >
Нет подходящих записей . Смените фильтры или поиск .
< / p >
)
) }
< div className = "publication-visibility__actions" style = { { marginTop : '0.75rem' } } >
< button
type = "button"
className = "btn btn-ghost"
disabled = { assignSelectedInList . length === 0 }
onClick = { postAssign }
>
Назначить выбранных
{ assignSelectedInList . length > 0
? ` ( ${ assignSelectedInList . length } ) `
: '' }
< / button >
< / div >
) : (
! assignLoadBusy && (
< p className = "text-muted" style = { { margin : '0.5rem 0' } } >
Нет подходящих записей . Смените фильтры или поиск .
< / p >
)
) }
< div className = "inline-actions" style = { { marginTop : '0.75rem' } } >
< button
type = "button"
className = "btn btn-ghost"
disabled = { assignSelectedInList . length === 0 }
onClick = { postAssign }
>
Назначить выбранных
{ assignSelectedInList . length > 0
? ` ( ${ assignSelectedInList . length } ) `
: '' }
< / button >
{ assignMsg && < p className = "text-muted" style = { { marginTop : 8 , marginBottom : 0 } } > { assignMsg } < / p > }
< / div >
{ assignMsg && < p className = "text-muted" > { assignMsg } < / p > }
< / AccSection >
) }
) }
< / AccSection >
< div
className = "test-detail-fixed-actions"