Merge pull request #5257 from christianbeeznest/GH-3616-6

Exercise: Fix bugs and enhance UI for exercises and questions - refs #3616
pull/5258/head
christianbeeznest 2 years ago committed by GitHub
commit 9ca9904c3e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 53
      assets/css/app.scss
  2. 99
      assets/css/scss/_exercise.scss
  3. 6
      assets/vue/composables/fileUtils.js
  4. 4
      public/main/exercise/TestCategory.php
  5. 15
      public/main/exercise/exercise.class.php
  6. 3
      public/main/exercise/exercise.php
  7. 5
      public/main/exercise/question_pool.php
  8. 6
      public/main/inc/ajax/exercise.ajax.php
  9. 28
      public/main/inc/lib/exercise.lib.php
  10. 8
      public/main/inc/lib/sortable_table.class.php
  11. 7
      public/main/my_space/exercise_category_report.php
  12. 4
      public/main/session/index.php

@ -88,6 +88,59 @@
align-items: normal !important;
}
.data_table, .table-striped {
@apply border-collapse w-full mt-2;
thead th {
@apply bg-gray-20 text-gray-90 font-semibold text-left px-4 py-3 border-b border-gray-30 border-l border-r border-gray-30 text-center;
}
tbody td {
@apply px-4 py-3 border-b border-gray-30 border-l border-r border-gray-30;
}
tbody tr:nth-child(odd) {
@apply bg-gray-5;
}
tbody tr:hover {
background-color: #eff6ff;
}
.checkbox label {
@apply pl-4;
}
i.mdi {
@apply align-middle;
}
.mdi::before {
@apply inline-block;
font-size: inherit;
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
transform: translate(0, 0);
}
}
.sortable-buttons-actions {
@apply bg-gray-5 border border-gray-20 rounded shadow;
.btn {
@apply px-4 bg-white border border-gray-30 py-2 mr-2 text-gray-90 rounded cursor-pointer transition-all;
height: 35px;
}
.btn--action {
@apply bg-white border border-gray-30 py-1 px-3 text-sm rounded cursor-pointer text-gray-90;
}
.btn:hover, .plane:hover {
@apply bg-gray-25 text-gray-90;
}
}
// Alerts
.alert {

@ -72,42 +72,6 @@
padding: 5px;
}
.data_table, .table-striped {
@apply border-collapse w-full mt-2;
thead th {
@apply bg-gray-20 text-gray-90 font-semibold text-left px-4 py-3 border-b border-gray-30 border-l border-r border-gray-30 text-center;
}
tbody td {
@apply px-4 py-3 border-b border-gray-30 border-l border-r border-gray-30;
}
tbody tr:nth-child(odd) {
@apply bg-gray-5;
}
tbody tr:hover {
background-color: #eff6ff;
}
.checkbox label {
@apply pl-4;
}
i.mdi {
@apply align-middle;
}
.mdi::before {
@apply inline-block;
font-size: inherit;
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
transform: translate(0, 0);
}
}
.question-pool-table-actions {
display: flex;
align-items: center;
@ -283,22 +247,13 @@
}
.question-header {
display: flex;
align-items: center;
justify-content: center;
@apply flex items-center justify-center border border-gray-30 rounded shadow-md mb-5;
background-color: #f8f9fa;
padding: 15px;
border: 1px solid #ddd;
border-radius: 4px;
padding: 2px;
box-shadow: 0 2px 3px rgba(0, 0, 0, 0.1);
margin-bottom: 20px;
> div {
display: flex;
align-items: center;
justify-content: center;
text-align: center;
padding: 0.75rem;
@apply flex items-center justify-center text-center p-3;
}
.col-sm-5 {
@ -315,17 +270,14 @@
.col-sm-1.text-right,
.col-sm-2.text-right {
justify-content: flex-end;
text-align: right;
@apply justify-end;
}
@media (max-width: 768px) {
flex-direction: column;
@apply flex-col;
> div {
text-align: left;
width: 100%;
padding: 0.5rem 0;
@apply text-left w-full py-2;
}
}
}
@ -370,6 +322,45 @@
}
}
.card {
border: 1px solid #ddd;
border-radius: 4px;
box-shadow: 0 2px 5px rgba(0,0,0,0.15);
background-color: #fff;
margin-bottom: 20px;
}
.card .flex {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 15px;
}
.card .flex .relative {
position: relative;
font-size: 16px;
font-weight: bold;
}
.card .flex a {
margin-left: 10px;
font-size: 22px;
color: #333;
}
.card .sectioncomment {
padding: 15px;
background-color: #f7f7f7;
}
.card span {
float: right;
margin-right: 15px;
font-size: 14px;
color: #666;
}
.question_menu {
@apply p-4 flex flex-row gap-1;
}

@ -17,9 +17,11 @@ export function useFileUtils() {
}
const isHtml = (fileData) => {
if (!isFile(fileData)) {
return false;
}
const mimeType = fileData.resourceNode.resourceFile.mimeType
const isHtml = mimeType.split("/")[1].toLowerCase() === "html"
return isFile(fileData) && isHtml
return mimeType.split("/")[1].toLowerCase() === "html"
}
const isFile = (fileData) => {

@ -1080,9 +1080,9 @@ class TestCategory
*
* @return CQuizQuestionCategory[]
*/
public static function getCategories($courseId, $sessionId = 0)
public static function getCategories(int $courseId, int $sessionId = 0): array
{
if (empty($courseId)) {
if (!($courseId > 0)) {
return [];
}

@ -8989,9 +8989,8 @@ class Exercise
}
$style = '';
if (0 === $exerciseEntity->getActive() || false === $visibility) {
if (!$visibility) {
$style = 'color:grey';
//$title = Display::tag('font', $cut_title, ['style' => 'color:grey']);
}
$title = $cut_title;
@ -9108,12 +9107,12 @@ class Exercise
$visibility = Display::getMdiIcon(StateIcon::PRIVATE_VISIBILITY, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('AddedToLPCannotBeAccessed')
);
} else {
if (0 === $exerciseEntity->getActive()) {
if (!$exerciseEntity->isVisible($course, $session)) {
$visibility = Display::url(
Display::getMdiIcon(StateIcon::PRIVATE_VISIBILITY, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Activate')
),
'exercise.php?'.api_get_cidreq(
).'&choice=enable&sec_token='.$token.'&exerciseId='.$exerciseId
).'&action=enable&sec_token='.$token.'&exerciseId='.$exerciseId
);
} else {
// else if not active
@ -9121,7 +9120,7 @@ class Exercise
Display::getMdiIcon(StateIcon::PUBLIC_VISIBILITY, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Deactivate')
),
'exercise.php?'.api_get_cidreq(
).'&choice=disable&sec_token='.$token.'&exerciseId='.$exerciseId
).'&action=disable&sec_token='.$token.'&exerciseId='.$exerciseId
);
}
}
@ -9164,7 +9163,7 @@ class Exercise
Display::getMdiIcon(StateIcon::PRIVATE_VISIBILITY, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Activate')
),
'exercise.php?'.api_get_cidreq(
).'&choice=enable&sec_token='.$token.'&exerciseId='.$exerciseId
).'&action=enable&sec_token='.$token.'&exerciseId='.$exerciseId
);
} else {
// else if not active
@ -9172,7 +9171,7 @@ class Exercise
Display::getMdiIcon(StateIcon::PUBLIC_VISIBILITY, 'ch-tool-icon', null, ICON_SIZE_SMALL, get_lang('Deactivate')
),
'exercise.php?'.api_get_cidreq(
).'&choice=disable&sec_token='.$token.'&exerciseId='.$exerciseId
).'&action=disable&sec_token='.$token.'&exerciseId='.$exerciseId
);
}
}
@ -9192,7 +9191,7 @@ class Exercise
api_htmlentities(get_lang('Are you sure to copy'), ENT_QUOTES)
)." ".addslashes($title)."?"."')) return false;",
'href' => 'exercise.php?'.api_get_cidreq(
).'&choice=copy_exercise&sec_token='.$token.'&exerciseId='.$exerciseId,
).'&action=copy_exercise&sec_token='.$token.'&exerciseId='.$exerciseId,
]
);
}

@ -196,9 +196,8 @@ if ($is_allowedToEdit && !empty($action)) {
// list of exercises in a course/session
// we got variable $courseId $courseInfo session api_get_session_id()
$exerciseList = ExerciseLib::get_all_exercises_for_course_id(
$courseInfo,
$sessionId,
$courseId,
$sessionId,
false
);

@ -384,9 +384,8 @@ $categoryList = TestCategory::getCategoriesIdAndName($selected_course);
// Get exercise list for this course
$exercise_list = ExerciseLib::get_all_exercises_for_course_id(
$course_info,
$session_id,
$selected_course,
$session_id,
false
);
@ -898,7 +897,7 @@ if (isset($fromExercise) && $fromExercise > 0) {
} else {
$actions .= '<a href="exercise.php?'.api_get_cidreq().'">'.
Display::getMdiIcon(ActionIcon::BACK, 'ch-tool-icon', null, ICON_SIZE_MEDIUM, get_lang('Back to tests list')).'</a>';
$actions .= "<a href='admin.php?exerciseId=0'>".
$actions .= '<a href="question_create.php?'.api_get_cidreq().'">'.
Display::getMdiIcon(ActionIcon::ADD, 'ch-tool-icon', null, ICON_SIZE_MEDIUM, get_lang('New question')).'</a>';
}
echo Display::toolbarAction('toolbar', [$actions]);

@ -24,9 +24,8 @@ switch ($action) {
$data = [];
$onlyActiveExercises = !(api_is_platform_admin(true) || api_is_course_admin());
$results = ExerciseLib::get_all_exercises_for_course_id(
null,
$session_id,
$course_id,
$session_id,
$onlyActiveExercises
);
@ -952,9 +951,8 @@ switch ($action) {
break;
case 'get_quiz_embeddable':
$exercises = ExerciseLib::get_all_exercises_for_course_id(
api_get_course_info(),
api_get_session_id(),
api_get_course_int_id(),
api_get_session_id(),
false
);

@ -3060,29 +3060,25 @@ EOT;
* from a course from a session
* (if a session_id is provided we will show all the exercises in the
* course + all exercises in the session).
*
* @param array course data
* @param int session id
* @param int course c_id
* @param bool $only_active_exercises
*
* @return array array with exercise data
* modified by Hubert Borderiou
*/
public static function get_all_exercises_for_course_id(
$course_info = null,
$session_id = 0,
$course_id = 0,
$only_active_exercises = true
) {
$course = api_get_course_entity($course_id);
$session = api_get_session_entity($session_id);
int $courseId,
int $sessionId = 0,
bool $onlyActiveExercises = true
): array {
if (!($courseId > 0)) {
return [];
}
$course = api_get_course_entity($courseId);
$session = api_get_session_entity($sessionId);
$repo = Container::getQuizRepository();
$qb = $repo->getResourcesByCourse($course, $session);
if ($only_active_exercises) {
if ($onlyActiveExercises) {
$qb->andWhere('resource.active = 1');
} else {
$qb->andWhere('resource.active IN (1, 0)');

@ -380,7 +380,7 @@ class SortableTable extends HTML_Table
if ($this->get_pager()->numPages() > 1) {
$form = $this->get_page_select_form();
$nav = $this->get_navigation_html();
$html = '<div class="q-card">';
$html = '<div class="q-card sortable-buttons-actions">';
$html .= '<div class="flex flex-row justify-between pager-bar">';
$html .= '<div class="col">';
$html .= '<div class="pb-2 pt-2 pager-select">'.$form.'</div>';
@ -417,18 +417,18 @@ class SortableTable extends HTML_Table
}
}
$html .= '<input type="hidden" name="action">';
$html .= '<div class="q-card p-2 mb-4">';
$html .= '<div class="q-card p-2 mb-4 sortable-buttons-actions">';
$html .= '<div class="flex flex-row justify-between">';
if (count($this->form_actions) > 0) {
$html .= '<div class="flex flex-row justify-between" role="group">';
$html .= '<a
class="btn btn--primary mr-2"
class="btn btn--action mr-2"
href="?'.$params.'&amp;'.$this->param_prefix.'selectall=1"
onclick="javascript: setCheckbox(true, \''.$table_id.'\'); return false;">'.
get_lang('Select all').'</a>';
$html .= '<a
class="btn btn--primary mr-2"
class="btn btn--action mr-2"
href="?'.$params.'"
onclick="javascript: setCheckbox(false, \''.$table_id.'\'); return false;">'.
get_lang('Deselect all').'</a> ';

@ -62,12 +62,7 @@ if (empty($courseId)) {
['target' => '_blank']
);
$form->addLabel(get_lang('Course'), $courseLabel);
$exerciseList = ExerciseLib::get_all_exercises_for_course_id(
$courseInfo,
0,
$courseId,
true
);
$exerciseList = ExerciseLib::get_all_exercises_for_course_id($courseId);
if (!empty($exerciseList)) {
$options = [];

@ -59,10 +59,8 @@ foreach ($courseList as $course) {
}
$exerciseList = ExerciseLib::get_all_exercises_for_course_id(
$course,
$session_id,
$course['real_id'],
true
$session_id
);
$exerciseListNew = [];

Loading…
Cancel
Save