diff --git a/.htaccess b/.htaccess index fd62a99e62..d6a4a37078 100644 --- a/.htaccess +++ b/.htaccess @@ -38,5 +38,8 @@ RewriteRule ^courses/([^/]+)/course-pic.png$ app/courses/$1/course-pic.png [QSA, # About session RewriteRule ^session/(\d{1,})/about/?$ main/session/about.php?session_id=$1 [L] +# Issued individual badge friendly URL +RewriteRule ^badge/(\d{1,}) main/badge/issued.php?issue=$1 [L] + # Issued badges friendly URL -RewriteRule ^badge/(\d{1,})/user/(\d{1,}) main/badge/issued.php?skill=$1&user=$2 [L] +RewriteRule ^skill/(\d{1,})/user/(\d{1,}) main/badge/issued_all.php?skill=$1&user=$2 [L] diff --git a/app/Migrations/Schema/V111/Version20160405112100.php b/app/Migrations/Schema/V111/Version20160405112100.php new file mode 100644 index 0000000000..4ab6db513e --- /dev/null +++ b/app/Migrations/Schema/V111/Version20160405112100.php @@ -0,0 +1,46 @@ +addSql( + 'CREATE TABLE skill_level_profile (id INT AUTO_INCREMENT NOT NULL, name VARCHAR(255) NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB' + ); + $this->addSql( + 'CREATE TABLE skill_level (id INT AUTO_INCREMENT NOT NULL, profile_id INT NOT NULL, name VARCHAR(255) NOT NULL, position INT, short_name VARCHAR(255), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB' + ); + $this->addSql( + 'ALTER TABLE skill_rel_user ADD acquired_level INT, ADD argumentation TEXT, ADD argumentation_author_id INT, MODIFY course_id INT, MODIFY session_id INT' + ); + $this->addSql( + 'CREATE TABLE skill_rel_user_comment (id INT AUTO_INCREMENT NOT NULL, skill_rel_user_id INT NOT NULL, feedback_giver_id INT NOT NULL, feedback_text TEXT, feedback_value INT, feedback_datetime DATETIME, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB' + ); + $this->addSql( + 'ALTER TABLE skill ADD profile_id INT' + ); + } + + /** + * @param Schema $schema + */ + public function down(Schema $schema) + { + $this->addSql( + 'ALTER TABLE skill_rel_user DROP COLUMN acquired_level, DROP COLUMN argumentation, DROP COLUMN argumentation_author_id, MODIFY course_id INT NOT NULL, MODIFY session_id INT NOT NULL' + ); + $this->addSql( + 'ALTER TABLE skill DROP COLUMN profile_id' + ); + $this->addSql('DROP TABLE skill_level'); + $this->addSql('DROP TABLE skill_level_profile'); + } +} \ No newline at end of file diff --git a/main/admin/index.php b/main/admin/index.php index 7eb109625c..a00ee73a40 100644 --- a/main/admin/index.php +++ b/main/admin/index.php @@ -386,6 +386,7 @@ if (api_is_platform_admin()) { $items[] = array('url' => 'skills_wheel.php', 'label' => get_lang('SkillsWheel')); $items[] = array('url' => 'skills_import.php', 'label' => get_lang('SkillsImport')); $items[] = array('url' => 'skill_list.php', 'label' => get_lang('ManageSkills')); + $items[] = array('url'=>'skill.php', 'label' => get_lang('ManageSkillsLevels')); //$items[] = array('url'=>'skills_profile.php', 'label' => get_lang('SkillsProfile')); $items[] = array( 'url' => api_get_path(WEB_CODE_PATH) . 'social/skills_ranking.php', diff --git a/main/admin/skill.php b/main/admin/skill.php new file mode 100644 index 0000000000..e8851105ea --- /dev/null +++ b/main/admin/skill.php @@ -0,0 +1,93 @@ +getRepository('ChamiloSkillBundle:Profile')->findAll(); +$list = $em->getRepository('ChamiloCoreBundle:Skill')->findAll(); + +$listAction = api_get_self(); + +$action = ''; +if (isset($_GET['action']) && in_array($_GET['action'], ['add', 'edit', 'delete'])) { + $action = $_GET['action']; +} + +$id = isset($_GET['id']) ? $_GET['id'] : ''; + +$item = null; +if (!empty($id)) { + /** @var \Chamilo\CoreBundle\Entity\Skill $item */ + $item = $em->getRepository('ChamiloCoreBundle:Skill')->find($id); + if (!$item) { + api_not_allowed(); + } +} + +$form = new FormValidator('Skill', 'GET', api_get_self().'?action='.$action.'&id='.$id); +$form->addSelectFromCollection('profile_id', get_lang('Profile'), $profiles, null, true); +$form->addHidden('action', $action); +$form->addHidden('id', $id); +$form->addButtonSave(get_lang('Update')); + +if (!empty($item)) { + $profile = $item->getProfile(); + if ($profile) { + $form->setDefaults( + [ + 'profile_id' => $item->getProfile()->getId(), + ] + ); + } + $form->addHeader($item->getName()); +} +$formToDisplay = $form->returnForm(); + +$interbreadcrumb[] = array ('url' => 'index.php', 'name' => get_lang('PlatformAdmin')); +$interbreadcrumb[] = array ('url' => api_get_self(), 'name' => get_lang('ManageSkillsLevels')); + +$tpl = new Template($action); +switch ($action) { + case 'edit': + $tpl->assign('form', $formToDisplay); + $tpl->assign('actions', Display::url(get_lang('List'), $listAction)); + + if ($form->validate()) { + $values = $form->exportValues(); + + $profile = $em->getRepository('ChamiloSkillBundle:Profile')->find($values['profile_id']); + $item->setProfile($profile); + + $em->persist($item); + $em->flush(); + header('Location: '.$listAction); + exit; + } + + break; + case 'delete': + $tpl->assign('actions', Display::url(get_lang('List'), $listAction)); + $em->remove($item); + $em->flush(); + header('Location: '.$listAction); + exit; + + break; + default: + break; +} + +$tpl->assign('list', $list); + +$contentTemplate = $tpl->fetch('default/admin/skill.tpl'); +$tpl->assign('content', $contentTemplate); +$tpl->display_one_col_template(); diff --git a/main/admin/skill_level.php b/main/admin/skill_level.php new file mode 100644 index 0000000000..bff2e4ed56 --- /dev/null +++ b/main/admin/skill_level.php @@ -0,0 +1,113 @@ +getRepository('ChamiloSkillBundle:Profile')->findAll(); +$list = $em->getRepository('ChamiloSkillBundle:Level')->findAll(); + +$listAction = api_get_self(); + +$action = ''; +if (isset($_GET['action']) && in_array($_GET['action'], ['add', 'edit', 'delete', 'add_level'])) { + $action = $_GET['action']; +} + +$id = isset($_GET['id']) ? $_GET['id'] : ''; + +$item = null; +if (!empty($id)) { + /** @var \Chamilo\SkillBundle\Entity\Level $item */ + $item = $em->getRepository('ChamiloSkillBundle:Level')->find($id); + if (!$item) { + api_not_allowed(); + } +} + +$form = new FormValidator('Level', 'GET', api_get_self().'?action='.$action.'&id='.$id); +$form->addText('name', get_lang('Name')); +$form->addText('short_name', get_lang('ShortName')); +$form->addSelectFromCollection('profile_id', get_lang('Profile'), $profiles); +$form->addHidden('action', $action); +$form->addHidden('id', $id); +$form->addButtonSave(get_lang('Save')); + +if (!empty($item)) { + $form->setDefaults([ + 'name' => $item->getName(), + 'short_name' => $item->getShortName(), + 'profile_id' => $item->getProfile()->getId(), + ]); +} +$formToDisplay = $form->returnForm(); + +$interbreadcrumb[] = array ('url' => 'index.php', 'name' => get_lang('PlatformAdmin')); +$interbreadcrumb[] = array ('url' => api_get_self(), 'name' => get_lang('SkillProfile')); + +$tpl = new Template($action); +switch ($action) { + case 'add': + $tpl->assign('form', $formToDisplay); + if ($form->validate()) { + $values = $form->exportValues(); + $item = new \Chamilo\SkillBundle\Entity\Level(); + $item->setName($values['name']); + $item->setShortName($values['short_name']); + $profile = $em->getRepository('ChamiloSkillBundle:Profile')->find($values['profile_id']); + $item->setProfile($profile); + + $em->persist($item); + $em->flush(); + header('Location: '.$listAction); + exit; + } + $tpl->assign('actions', Display::url(get_lang('List'), $listAction)); + break; + case 'edit': + $tpl->assign('form', $formToDisplay); + $tpl->assign('actions', Display::url(get_lang('List'), $listAction)); + + if ($form->validate()) { + $values = $form->exportValues(); + + $item->setName($values['name']); + $item->setShortName($values['short_name']); + $profile = $em->getRepository('ChamiloSkillBundle:Profile')->find($values['profile_id']); + $item->setProfile($profile); + + $em->persist($item); + $em->flush(); + header('Location: '.$listAction); + exit; + } + + break; + case 'delete': + $tpl->assign('actions', Display::url(get_lang('List'), $listAction)); + $em->remove($item); + $em->flush(); + header('Location: '.$listAction); + exit; + + break; + default: + $tpl->assign('actions', Display::url(get_lang('Add'), api_get_self().'?action=add')); +} + +$tpl->assign('list', $list); + +$contentTemplate = $tpl->fetch('default/admin/skill_level.tpl'); +$tpl->assign('content', $contentTemplate); +$tpl->display_one_col_template(); diff --git a/main/admin/skill_profile.php b/main/admin/skill_profile.php new file mode 100644 index 0000000000..2a4acc8108 --- /dev/null +++ b/main/admin/skill_profile.php @@ -0,0 +1,122 @@ +getRepository('ChamiloSkillBundle:Profile')->findAll(); + +$listAction = api_get_self(); + +$action = ''; +if (isset($_GET['action']) && in_array($_GET['action'], ['add', 'edit', 'delete', 'move_up', 'move_down'])) { + $action = $_GET['action']; +} + +$id = isset($_GET['id']) ? $_GET['id'] : ''; + +$item = null; +if (!empty($id)) { + $item = $em->getRepository('ChamiloSkillBundle:Profile')->find($id); + if (!$item) { + api_not_allowed(); + } +} + +$form = new FormValidator('Profile', 'GET', api_get_self().'?action='.$action.'&id='.$id); +$form->addText('name', get_lang('Name')); +$form->addHidden('action', $action); +$form->addHidden('id', $id); +$form->addButtonSave(get_lang('Save')); + +if (!empty($item)) { + $form->setDefaults(['name' => $item->getName()]); +} +$formToDisplay = $form->returnForm(); + +$interbreadcrumb[] = array ('url' => 'index.php', 'name' => get_lang('PlatformAdmin')); +$interbreadcrumb[] = array ('url' => 'skill.php', 'name' => get_lang('ManageSkillsLevels')); +$interbreadcrumb[] = array ('url' => api_get_self(), 'name' => get_lang('SkillProfile')); + +$tpl = new Template($action); +switch ($action) { + case 'move_up': + /** @var \Chamilo\SkillBundle\Entity\Level $item */ + $item = $em->getRepository('ChamiloSkillBundle:Level')->find($_GET['level_id']); + + $position = $item->getPosition(); + + if (!empty($position)) { + $item->setPosition($position-1); + } + $em->persist($item); + $em->flush(); + header('Location: '.$listAction); + exit; + break; + case 'move_down': + /** @var \Chamilo\SkillBundle\Entity\Level $item */ + $item = $em->getRepository('ChamiloSkillBundle:Level')->find($_GET['level_id']); + + $position = $item->getPosition(); + + $item->setPosition($position+1); + + $em->persist($item); + $em->flush(); + header('Location: '.$listAction); + exit; + break; + case 'add': + $tpl->assign('form', $formToDisplay); + if ($form->validate()) { + $values = $form->exportValues(); + $item = new \Chamilo\SkillBundle\Entity\Profile(); + $item->setName($values['name']); + $em->persist($item); + $em->flush(); + header('Location: '.$listAction); + exit; + } + $tpl->assign('actions', Display::url(get_lang('List'), $listAction)); + break; + case 'edit': + $tpl->assign('form', $formToDisplay); + $tpl->assign('actions', Display::url(get_lang('List'), $listAction)); + + if ($form->validate()) { + $values = $form->exportValues(); + $item->setName($values['name']); + $em->persist($item); + $em->flush(); + header('Location: '.$listAction); + exit; + } + + break; + case 'delete': + $tpl->assign('actions', Display::url(get_lang('List'), $listAction)); + $em->remove($item); + $em->flush(); + header('Location: '.$listAction); + exit; + + break; + default: + $tpl->assign('actions', Display::url(get_lang('Add'), api_get_self().'?action=add')); +} + +$tpl->assign('list', $list); + +$contentTemplate = $tpl->fetch('default/admin/skill_profile.tpl'); +$tpl->assign('content', $contentTemplate); +$tpl->display_one_col_template(); diff --git a/main/admin/user_list.php b/main/admin/user_list.php index 75d630b8d0..a474ccf096 100755 --- a/main/admin/user_list.php +++ b/main/admin/user_list.php @@ -530,6 +530,15 @@ function modify_filter($user_id, $url_params, $row) { } } + $allowAssignSkill = api_is_platform_admin(false, true); + + if ($allowAssignSkill) { + $result .= Display::url( + Display::return_icon('skill-badges.png', get_lang('AssignSkill'), null, ICON_SIZE_SMALL), + api_get_path(WEB_CODE_PATH) . 'badge/assign.php?' . http_build_query(['user' => $user_id]) + ); + } + if ($is_admin) { $result .= Display::return_icon('admin_star.png', get_lang('IsAdministrator'),array('width'=> ICON_SIZE_SMALL, 'heigth'=> ICON_SIZE_SMALL)); } else { diff --git a/main/badge/assign.php b/main/badge/assign.php new file mode 100644 index 0000000000..d54bac8324 --- /dev/null +++ b/main/badge/assign.php @@ -0,0 +1,183 @@ + + * @package chamilo.badge + */ + +use \Chamilo\CoreBundle\Entity\Skill; +use \Chamilo\CoreBundle\Entity\SkillRelUser; + +require_once '../inc/global.inc.php'; + +if (!api_is_platform_admin(false, true)) { + api_not_allowed(true); +} + +if (!isset($_REQUEST['user'])) { + api_not_allowed(true); +} + +$entityManager = Database::getManager(); +$skillRepo = $entityManager->getRepository('ChamiloCoreBundle:Skill'); +$skillRelSkill = $entityManager->getRepository('ChamiloCoreBundle:SkillRelSkill'); +$skillLevelRepo = $entityManager->getRepository('ChamiloSkillBundle:Level'); +$skillUserRepo = $entityManager->getRepository('ChamiloCoreBundle:SkillRelUser'); +$user = $entityManager->find('ChamiloUserBundle:User', $_REQUEST['user']); + +if (!$user) { + Display::addFlash( + Display::return_message(get_lang('NoUser'), 'error') + ); + + header('Location: ' . api_get_path(WEB_PATH)); + exit; +} + +$skills = $skillRepo->findBy([ + 'status' => Skill::STATUS_ENABLED +]); + +$url = api_get_path(WEB_CODE_PATH)."badge/assign.php?user=".$_REQUEST['user']."&id="; + +$htmlHeadXtra[] = '' + . ''; + +$skillsOptions = []; +$acquiredLevel = []; +$formDefaultValues = []; + +foreach ($skills as $skill) { + $skillsOptions[$skill->getId()] = $skill->getName(); +} + +$skillId = isset($_REQUEST['id']) ? intval($_REQUEST['id']) : key($skillsOptions); + +$profile = $skillRepo->find($skillId)->getProfile(); + +if (!$profile) { + + $skillRelSkill = new SkillRelSkill(); + $parents = $skillRelSkill->get_skill_parents($skillId); + + krsort($parents); + + foreach ($parents as $parent) { + $skillParentId = $parent['skill_id']; + $profile = $skillRepo->find($skillParentId)->getProfile(); + + if ($profile) { + break; + } + + if (!$profile && $parent['parent_id'] == 0) { + $profile = $skillLevelRepo->findAll(); + $profile = isset($profile[0]) ? $profile[0] : false; + } + } +} + +if ($profile) { + + $profileId = $profile->getId(); + + $levels = $skillLevelRepo->findBy([ + 'profile' => $profileId + ]); + + foreach ($levels as $level) { + $profileLevels[$level->getPosition()][$level->getId()] = $level->getName(); + } + + ksort($profileLevels); // Sort the array by Position. + + foreach ($profileLevels as $profileLevel) { + $profileId = key($profileLevel); + $acquiredLevel[$profileId] = $profileLevel[$profileId]; + } + +} + +$formDefaultValues = ['skill' => $skillId]; + +$form = new FormValidator('assign_skill'); +$form->addText('user_name', get_lang('UserName'), false); +$form->addSelect('skill', get_lang('Skill'), $skillsOptions, ['id' => 'skill']); +$form->addHidden('user', $user->getId()); +$form->addHidden('id', $skillId); +$form->addRule('skill', get_lang('ThisFieldIsRequired'), 'required'); +$form->addSelect('acquired_level', get_lang('AcquiredLevel'), $acquiredLevel); +$form->addRule('acquired_level', get_lang('ThisFieldIsRequired'), 'required'); +$form->addTextarea('argumentation', get_lang('Argumentation'), ['rows' => 6]); +$form->applyFilter('argumentation', 'trim'); +$form->addButtonSave(get_lang('Save')); +$form->setDefaults($formDefaultValues); + +if ($form->validate()) { + $values = $form->exportValues(); + + $skill = $skillRepo->find($values['skill']); + + if (!$skill) { + Display::addFlash( + Display::return_message(get_lang('SkillNotFound'), 'error') + ); + + header('Location: ' . api_get_self() . '?' . http_build_query(['user' => $user->getId()])); + exit; + } + + if ($user->hasSkill($skill)) { + Display::addFlash( + Display::return_message( + sprintf(get_lang('TheUserXHasAlreadyAchievedTheSkillY'), $user->getCompleteName(), $skill->getName()), + 'warning' + ) + ); + + header('Location: ' . api_get_self() . '?' . http_build_query(['user' => $user->getId()])); + exit; + } + + $skillUser = new SkillRelUser(); + $skillUser->setUser($user); + $skillUser->setSkill($skill); + $level = $skillLevelRepo->find(intval($values['acquired_level'])); + $skillUser->setAcquiredLevel($level); + $skillUser->setArgumentation($values['argumentation']); + $skillUser->setArgumentationAuthorId(api_get_user_id()); + $skillUser->setAcquiredSkillAt(new DateTime()); + $skillUser->setAssignedBy(0); + + $entityManager->persist($skillUser); + $entityManager->flush(); + + Display::addFlash( + Display::return_message( + sprintf(get_lang('SkillXAssignedToUserY'), $skill->getName(), $user->getCompleteName()), + 'success' + ) + ); + + header('Location: ' . api_get_path(WEB_PATH) . "badge/{$skillUser->getId()}"); + exit; +} + +$form->setDefaults(['user_name' => $user->getCompleteName()]); +$form->freeze(['user_name']); + +//View +$template = new Template(''); +$template->assign('header', get_lang('AssignSkill')); +$template->assign('content', $form->returnForm()); +$template->display_one_col_template(); \ No newline at end of file diff --git a/main/badge/issued.php b/main/badge/issued.php index 382cfa8e37..527198fbc5 100644 --- a/main/badge/issued.php +++ b/main/badge/issued.php @@ -3,41 +3,39 @@ /** * Show information about the issued badge * @author Angel Fernando Quiroz Campos + * @author José Loguercio Silva * @package chamilo.badge */ require_once '../inc/global.inc.php'; require_once '../inc/lib/baker.lib.php'; -$userId = isset($_GET['user']) ? intval($_GET['user']) : 0; -$skillId = isset($_GET['skill']) ? intval($_GET['skill']) : 0; +$issue = isset($_REQUEST['issue']) ? intval($_REQUEST['issue']) : 0; -if (!isset($_GET['user'], $_GET['skill'])) { +if (!$issue) { header('Location: ' . api_get_path(WEB_PATH)); exit; } $entityManager = Database::getManager(); -$user = $entityManager->find('ChamiloUserBundle:User', $_GET['user']); -$skill = $entityManager->find('ChamiloCoreBundle:Skill', $_GET['skill']); +$skillIssue = $entityManager->find('ChamiloCoreBundle:SkillRelUser', $issue); +$skillRepo = $entityManager->getRepository('ChamiloCoreBundle:Skill'); +$skillLevelRepo = $entityManager->getRepository('ChamiloSkillBundle:Level'); -if (!$user || !$skill) { +if (!$skillIssue) { Display::addFlash( - Display::return_message(get_lang('NoResults'), 'error') + Display::return_message(get_lang('TheUserXNotYetAchievedTheSkillX'), 'error') ); header('Location: ' . api_get_path(WEB_PATH)); exit; } -$skillUserRepo = $entityManager->getRepository('ChamiloCoreBundle:SkillRelUser'); -$userSkills = $skillUserRepo->findBy([ - 'userId' => $user->getId(), - 'skillId' => $skill->getId() -]); +$user = $skillIssue->getUser(); +$skill = $skillIssue->getSkill(); -if (!$userSkills) { +if (!$user || !$skill) { Display::addFlash( - Display::return_message(get_lang('TheUserXNotYetAchievedTheSkillX'), 'error') + Display::return_message(get_lang('NoResults'), 'error') ); header('Location: ' . api_get_path(WEB_PATH)); @@ -59,50 +57,165 @@ $skillInfo = [ 'courses' => [] ]; - - // Open Graph Markup $htmlHeadXtra[] = " - + "; -$badgeAssertions = []; +$currentUserId = api_get_user_id(); +$currentUser = $entityManager->find('ChamiloUserBundle:User', $currentUserId); +$allowDownloadExport = $currentUser ? $currentUser->getId() === $user->getId() : false; +$allowComment = $currentUser ? Skill::userCanAddFeedbackToUser($currentUser, $user) : false; +$skillIssueDate = api_get_local_time($skillIssue->getAcquiredSkillAt()); +$currentSkillLevel = get_lang('NoLevelAcquiredYet'); +if ($skillIssue->getAcquiredLevel()) { + $currentSkillLevel = $skillLevelRepo->find(['id' => $skillIssue->getAcquiredLevel()])->getName(); +} + +$argumentationAuthor = api_get_user_info($skillIssue->getArgumentationAuthorId()); + +$skillIssueInfo = [ + 'id' => $skillIssue->getId(), + 'datetime' => api_format_date($skillIssueDate, DATE_TIME_FORMAT_SHORT), + 'acquired_level' => $currentSkillLevel, + 'argumentation_author_id' => $skillIssue->getArgumentationAuthorId(), + 'argumentation_author_name' => api_get_person_name($argumentationAuthor['firstname'], $argumentationAuthor['lastname']), + 'argumentation' => $skillIssue->getArgumentation(), + 'source_name' => $skillIssue->getSourceName(), + 'user_id' => $skillIssue->getUser()->getId(), + 'user_complete_name' => $skillIssue->getUser()->getCompleteName(), + 'skill_id' => $skillIssue->getSkill()->getId(), + 'skill_badge_image' => $skillIssue->getSkill()->getWebIconPath(), + 'skill_name' => $skillIssue->getSkill()->getName(), + 'skill_short_code' => $skillIssue->getSkill()->getShortCode(), + 'skill_description' => $skillIssue->getSkill()->getDescription(), + 'skill_criteria' => $skillIssue->getSkill()->getCriteria(), + 'badge_assertion' => $skillIssue->getAssertionUrl(), + 'comments' => [], + 'feedback_average' => $skillIssue->getAverage() +]; -foreach ($userSkills as $userSkill) { - $sessionId = 0; - $course = $entityManager->find('ChamiloCoreBundle:Course', $userSkill->getCourseId()); - $courseName = $course ? $course->getTitle() : ''; +$skillIssueComments = $skillIssue->getComments(true); - if ($userSkill->getSessionId()) { - $session = $entityManager->find('ChamiloCoreBundle:Session', $userSkill->getSessionId()); - $sessionId = $session->getId(); - $courseName = "[{$session->getName()}] {$course->getTitle()}"; - } +$userId = $skillIssueInfo['user_id']; +$skillId = $skillIssueInfo['skill_id']; - $userSkillDate = api_get_local_time($userSkill->getAcquiredSkillAt()); - $skillInfo['courses'][] = [ - 'name' => $courseName, - 'date_issued' => api_format_date($userSkillDate, DATE_TIME_FORMAT_LONG) +foreach ($skillIssueComments as $comment) { + $commentDate = api_get_local_time($comment->getFeedbackDateTime()); + + $skillIssueInfo['comments'][] = [ + 'text' => $comment->getFeedbackText(), + 'value' => $comment->getFeedbackValue(), + 'giver_complete_name' => $comment->getFeedbackGiver()->getCompleteName(), + 'datetime' => api_format_date($commentDate, DATE_TIME_FORMAT_SHORT) ]; +} + +$acquiredLevel = []; + +$profile = $skillRepo->find($skillId)->getProfile(); - $assertionUrl = api_get_path(WEB_CODE_PATH) . "badge/assertion.php?"; - $assertionUrl .= http_build_query(array( - 'user' => $user->getId(), - 'skill' => $skill->getId(), - 'course' => $userSkill->getCourseId(), - 'session' => $userSkill->getSessionId() - )); +if (!$profile) { - $badgeAssertions[] = $assertionUrl; + $skillRelSkill = new SkillRelSkill(); + $parents = $skillRelSkill->get_skill_parents($skillId); + + krsort($parents); + + foreach ($parents as $parent) { + $skillParentId = $parent['skill_id']; + $profile = $skillRepo->find($skillParentId)->getProfile(); + + if ($profile) { + break; + } + + if (!$profile && $parent['parent_id'] == 0) { + $profile = $skillLevelRepo->findAll(); + $profile = $profile[0]; + } + } } -$allowExport = api_get_user_id() == $user->getId(); +if ($profile) { + + $profileId = $profile->getId(); -if ($allowExport) { + $levels = $skillLevelRepo->findBy([ + 'profile' => $profileId + ]); + + foreach ($levels as $level) { + $profileLevels[$level->getPosition()][$level->getId()] = $level->getName(); + } + + ksort($profileLevels); // Sort the array by Position. + + foreach ($profileLevels as $profileLevel) { + $profileId = key($profileLevel); + $acquiredLevel[$profileId] = $profileLevel[$profileId]; + } + +} + +$formAcquiredLevel = new FormValidator('acquired_level'); +$formAcquiredLevel->addSelect('acquired_level', get_lang('AcquiredLevel'), $acquiredLevel); +$formAcquiredLevel->addHidden('user', $skillIssue->getUser()->getId()); +$formAcquiredLevel->addHidden('issue', $skillIssue->getId()); +$formAcquiredLevel->addButtonSend(get_lang('Save')); + +if ($formAcquiredLevel->validate() && $allowComment) { + $values = $formAcquiredLevel->exportValues(); + + $level = $skillLevelRepo->find(intval($values['acquired_level'])); + $skillIssue->setAcquiredLevel($level); + + $entityManager->persist($skillIssue); + $entityManager->flush(); + + header("Location: " . $skillIssue->getIssueUrl()); + exit; +} + +$form = new FormValidator('comment'); +$form->addTextarea('comment', get_lang('NewComment'), ['rows' => 4]); +$form->applyFilter('comment', 'trim'); +$form->addRule('comment', get_lang('ThisFieldIsRequired'), 'required'); +$form->addSelect( + 'value', + [get_lang('Value'), get_lang('RateTheSkillInPractice')], + ['-', 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] +); +$form->addHidden('user', $skillIssue->getUser()->getId()); +$form->addHidden('issue', $skillIssue->getId()); +$form->addButtonSend(get_lang('Send')); + +if ($form->validate() && $allowComment) { + $values = $form->exportValues(); + + $skillUserComment = new Chamilo\CoreBundle\Entity\SkillRelUserComment(); + $skillUserComment + ->setFeedbackDateTime(new DateTime) + ->setFeedbackGiver($currentUser) + ->setFeedbackText($values['comment']) + ->setFeedbackValue($values['value'] ? $values['value'] : null) + ->setSkillRelUser($skillIssue); + + $entityManager->persist($skillUserComment); + $entityManager->flush(); + + header("Location: " . $skillIssue->getIssueUrl()); + exit; +} + +$badgeInfoError = ""; +$personalBadge = ""; + +if ($allowDownloadExport) { $backpack = 'https://backpack.openbadges.org/'; $configBackpack = api_get_setting('openbadges_backpack'); @@ -112,28 +225,27 @@ if ($allowExport) { } $htmlHeadXtra[] = ''; -} - -$badgeInfoError = false; -$personalBadge = ""; - -if ($skill->getIcon()) { - $unbakedBadge = file_get_contents( - api_get_path(SYS_UPLOAD_PATH) . "badges/" . $skill->getIcon() - ); + $objSkill = new Skill(); + $assertionUrl = $skillIssueInfo['badge_assertion']; + $skills = $objSkill->get($skillId); + $unbakedBadge = api_get_path(SYS_UPLOAD_PATH) . "badges/".$skills['icon']; + if (!is_file($unbakedBadge)) { + $unbakedBadge = api_get_path(WEB_CODE_PATH).'img/icons/128/badges-default.png'; + } + $unbakedBadge = file_get_contents($unbakedBadge); + $badgeInfoError = false; + $personalBadge = ""; $png = new PNGImageBaker($unbakedBadge); if ($png->checkChunks("tEXt", "openbadges")) { $bakedInfo = $png->addChunk("tEXt", "openbadges", $assertionUrl); - $bakedBadge = UserManager::getUserPathById($userId, "system") . 'badges'; - + $bakedBadge = UserManager::getUserPathById($userId, "system"); + $bakedBadge = $bakedBadge.'badges'; if (!file_exists($bakedBadge)) { mkdir($bakedBadge, api_get_permissions_for_new_directories(), true); } - - $skillRelUserId = $userSkills[0]->getId(); - + $skillRelUserId = $skillIssueInfo['id']; if (!file_exists($bakedBadge . "/badge_" . $skillRelUserId)) { file_put_contents($bakedBadge . "/badge_" . $skillRelUserId . ".png", $bakedInfo); } @@ -141,7 +253,6 @@ if ($skill->getIcon()) { //Process to validate a baked badge $badgeContent = file_get_contents($bakedBadge . "/badge_" . $skillRelUserId . ".png"); $verifyBakedBadge = $png->extractBadgeInfo($badgeContent); - if (!is_array($verifyBakedBadge)) { $badgeInfoError = true; } @@ -153,17 +264,15 @@ if ($skill->getIcon()) { } } -$template = new Template(''); -$template->assign('skill_info', $skillInfo); -$template->assign('user_info', $userInfo); -$template->assign('allow_export', $allowExport); +$template = new Template(get_lang('IssuedBadgeInformation')); +$template->assign('issue_info', $skillIssueInfo); +$template->assign('allow_comment', $allowComment); +$template->assign('allow_download_export', $allowDownloadExport); +$template->assign('comment_form', $form->returnForm()); +$template->assign('acquired_level_form', $formAcquiredLevel->returnForm()); $template->assign('badge_error', $badgeInfoError); $template->assign('personal_badge', $personalBadge); -if ($allowExport) { - $template->assign('assertions', $badgeAssertions); -} - $content = $template->fetch( $template->get_template('skill/issued.tpl') ); diff --git a/main/badge/issued_all.php b/main/badge/issued_all.php new file mode 100644 index 0000000000..2e40c0ecac --- /dev/null +++ b/main/badge/issued_all.php @@ -0,0 +1,277 @@ + + * @package chamilo.badge + */ +require_once '../inc/global.inc.php'; +require_once '../inc/lib/baker.lib.php'; + +$userId = isset($_GET['user']) ? intval($_GET['user']) : 0; +$skillId = isset($_GET['skill']) ? intval($_GET['skill']) : 0; + +if (!$userId || !$skillId) { + header('Location: ' . api_get_path(WEB_PATH)); + exit; +} + +$entityManager = Database::getManager(); +$user = $entityManager->find('ChamiloUserBundle:User', $userId); +$skill = $entityManager->find('ChamiloCoreBundle:Skill', $skillId); +$skillRepo = $entityManager->getRepository('ChamiloCoreBundle:Skill'); +$skillUserRepo = $entityManager->getRepository('ChamiloCoreBundle:SkillRelUser'); +$skillLevelRepo = $entityManager->getRepository('ChamiloSkillBundle:Level'); + +$currentUserId = api_get_user_id(); + +if (!$user || !$skill) { + Display::addFlash( + Display::return_message(get_lang('NoResults'), 'error') + ); + + header('Location: ' . api_get_path(WEB_PATH)); + exit; +} + +$userSkills = $skillUserRepo->findBy([ + 'userId' => $user->getId(), + 'skillId' => $skill->getId() +]); + +$userInfo = [ + 'id' => $user->getId(), + 'complete_name' => $user->getCompleteName() +]; + +$skillInfo = [ + 'id' => $skill->getId(), + 'name' => $skill->getName(), + 'short_code' => $skill->getShortCode(), + 'description' => $skill->getDescription(), + 'criteria' => $skill->getCriteria(), + 'badge_image' => $skill->getWebIconPath(), + 'courses' => [] +]; + +$allUserBadges = []; + +foreach ($userSkills as $index => $skillIssue) { + $currentUser = $entityManager->find('ChamiloUserBundle:User', $currentUserId); + $allowDownloadExport = $currentUser ? $currentUser->getId() === $user->getId() : false; + $allowComment = $currentUser ? Skill::userCanAddFeedbackToUser($currentUser, $user) : false; + $skillIssueDate = api_get_local_time($skillIssue->getAcquiredSkillAt()); + $currentSkillLevel = get_lang('NoLevelAcquiredYet'); + if ($skillIssue->getAcquiredLevel()) { + $currentSkillLevel = $skillLevelRepo->find(['id' => $skillIssue->getAcquiredLevel()])->getName(); + } + $argumentationAuthor = api_get_user_info($skillIssue->getArgumentationAuthorId()); + + $skillIssueInfo = [ + 'id' => $skillIssue->getId(), + 'datetime' => api_format_date($skillIssueDate, DATE_TIME_FORMAT_SHORT), + 'acquired_level' => $currentSkillLevel, + 'argumentation_author_id' => $skillIssue->getArgumentationAuthorId(), + 'argumentation_author_name' => api_get_person_name($argumentationAuthor['firstname'], $argumentationAuthor['lastname']), + 'argumentation' => $skillIssue->getArgumentation(), + 'source_name' => $skillIssue->getSourceName(), + 'user_id' => $skillIssue->getUser()->getId(), + 'user_complete_name' => $skillIssue->getUser()->getCompleteName(), + 'skill_id' => $skillIssue->getSkill()->getId(), + 'skill_badge_image' => $skillIssue->getSkill()->getWebIconPath(), + 'skill_name' => $skillIssue->getSkill()->getName(), + 'skill_short_code' => $skillIssue->getSkill()->getShortCode(), + 'skill_description' => $skillIssue->getSkill()->getDescription(), + 'skill_criteria' => $skillIssue->getSkill()->getCriteria(), + 'badge_assertion' => $skillIssue->getAssertionUrl(), + 'comments' => [], + 'feedback_average' => $skillIssue->getAverage() + ]; + + $skillIssueComments = $skillIssue->getComments(true); + + $userId = $skillIssueInfo['user_id']; + $skillId = $skillIssueInfo['skill_id']; + + foreach ($skillIssueComments as $comment) { + $commentDate = api_get_local_time($comment->getFeedbackDateTime()); + + $skillIssueInfo['comments'][] = [ + 'text' => $comment->getFeedbackText(), + 'value' => $comment->getFeedbackValue(), + 'giver_complete_name' => $comment->getFeedbackGiver()->getCompleteName(), + 'datetime' => api_format_date($commentDate, DATE_TIME_FORMAT_SHORT) + ]; + } + + $acquiredLevel = []; + + $profile = $skillRepo->find($skillId)->getProfile(); + + if (!$profile) { + + $skillRelSkill = new SkillRelSkill(); + $parents = $skillRelSkill->get_skill_parents($skillId); + + krsort($parents); + + foreach ($parents as $parent) { + $skillParentId = $parent['skill_id']; + $profile = $skillRepo->find($skillParentId)->getProfile(); + + if ($profile) { + break; + } + + if (!$profile && $parent['parent_id'] == 0) { + $profile = $skillLevelRepo->findAll(); + $profile = $profile[0]; + } + } + } + + if ($profile) { + + $profileId = $profile->getId(); + + $levels = $skillLevelRepo->findBy([ + 'profile' => $profileId + ]); + + foreach ($levels as $level) { + $profileLevels[$level->getPosition()][$level->getId()] = $level->getName(); + } + + ksort($profileLevels); // Sort the array by Position. + + foreach ($profileLevels as $profileLevel) { + $profileId = key($profileLevel); + $acquiredLevel[$profileId] = $profileLevel[$profileId]; + } + + } + + $formAcquiredLevel = new FormValidator('acquired_level'.$skillIssue->getId(), 'post', $skillIssue->getIssueUrlAll()); + $formAcquiredLevel->addSelect('acquired_level', get_lang('AcquiredLevel'), $acquiredLevel); + $formAcquiredLevel->addHidden('user', $skillIssue->getUser()->getId()); + $formAcquiredLevel->addHidden('issue', $skillIssue->getId()); + $formAcquiredLevel->addButtonSend(get_lang('Save')); + + if ($formAcquiredLevel->validate() && $allowComment) { + $values = $formAcquiredLevel->exportValues(); + + $level = $skillLevelRepo->find(intval($values['acquired_level'])); + $skillIssue->setAcquiredLevel($level); + + $entityManager->persist($skillIssue); + $entityManager->flush(); + + header("Location: " . $skillIssue->getIssueUrlAll()); + exit; + } + + $form = new FormValidator('comment'.$skillIssue->getId(), 'post', $skillIssue->getIssueUrlAll()); + $form->addTextarea('comment', get_lang('NewComment'), ['rows' => 4]); + $form->applyFilter('comment', 'trim'); + $form->addRule('comment', get_lang('ThisFieldIsRequired'), 'required'); + $form->addSelect( + 'value', + [get_lang('Value'), get_lang('RateTheSkillInPractice')], + ['-', 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + ); + $form->addHidden('user', $skillIssue->getUser()->getId()); + $form->addHidden('issue', $skillIssue->getId()); + $form->addButtonSend(get_lang('Send')); + + if ($form->validate() && $allowComment) { + $values = $form->exportValues(); + + $skillUserComment = new Chamilo\CoreBundle\Entity\SkillRelUserComment(); + $skillUserComment + ->setFeedbackDateTime(new DateTime) + ->setFeedbackGiver($currentUser) + ->setFeedbackText($values['comment']) + ->setFeedbackValue($values['value'] ? $values['value'] : null) + ->setSkillRelUser($skillIssue); + + $entityManager->persist($skillUserComment); + $entityManager->flush(); + + header("Location: " . $skillIssue->getIssueUrlAll()); + exit; + } + + $badgeInfoError = ""; + $personalBadge = ""; + + if ($allowDownloadExport) { + $backpack = 'https://backpack.openbadges.org/'; + + $configBackpack = api_get_setting('openbadges_backpack'); + + if (strcmp($backpack, $configBackpack) !== 0) { + $backpack = $configBackpack; + } + + $htmlHeadXtra[] = ''; + $objSkill = new Skill(); + $assertionUrl = $skillIssueInfo['badge_assertion']; + $skills = $objSkill->get($skillId); + $unbakedBadge = api_get_path(SYS_UPLOAD_PATH) . "badges/".$skills['icon']; + if (!is_file($unbakedBadge)) { + $unbakedBadge = api_get_path(WEB_CODE_PATH).'img/icons/128/badges-default.png'; + } + + $unbakedBadge = file_get_contents($unbakedBadge); + $badgeInfoError = false; + $personalBadge = ""; + $png = new PNGImageBaker($unbakedBadge); + + if ($png->checkChunks("tEXt", "openbadges")) { + $bakedInfo = $png->addChunk("tEXt", "openbadges", $assertionUrl); + $bakedBadge = UserManager::getUserPathById($userId, "system"); + $bakedBadge = $bakedBadge.'badges'; + if (!file_exists($bakedBadge)) { + mkdir($bakedBadge, api_get_permissions_for_new_directories(), true); + } + $skillRelUserId = $skillIssueInfo['id']; + if (!file_exists($bakedBadge . "/badge_" . $skillRelUserId)) { + file_put_contents($bakedBadge . "/badge_" . $skillRelUserId . ".png", $bakedInfo); + } + + //Process to validate a baked badge + $badgeContent = file_get_contents($bakedBadge . "/badge_" . $skillRelUserId . ".png"); + $verifyBakedBadge = $png->extractBadgeInfo($badgeContent); + if (!is_array($verifyBakedBadge)) { + $badgeInfoError = true; + } + + if (!$badgeInfoError) { + $personalBadge = UserManager::getUserPathById($userId, "web"); + $personalBadge = $personalBadge."badges/badge_" . $skillRelUserId . ".png"; + } + } + } + + $allUserBadges[$index]['issue_info'] = $skillIssueInfo; + $allUserBadges[$index]['allow_comment'] = $allowComment; + $allUserBadges[$index]['allow_download_export'] = $allowDownloadExport; + $allUserBadges[$index]['comment_form'] = $form->returnForm(); + $allUserBadges[$index]['acquired_level_form'] = $formAcquiredLevel->returnForm(); + $allUserBadges[$index]['badge_error'] = $badgeInfoError; + $allUserBadges[$index]['personal_badge'] = $personalBadge; + +} + +$template = new Template(get_lang('IssuedBadgeInformation')); +$template->assign('user_badges', $allUserBadges); + + +$content = $template->fetch( + $template->get_template('skill/issued_all.tpl') +); + +$template->assign('header', get_lang('IssuedBadgeInformation')); +$template->assign('content', $content); +$template->display_one_col_template(); diff --git a/main/inc/lib/database.lib.php b/main/inc/lib/database.lib.php index ffafdec81c..aa0bff9c54 100755 --- a/main/inc/lib/database.lib.php +++ b/main/inc/lib/database.lib.php @@ -141,6 +141,7 @@ class Database 'ChamiloCoreBundle' => 'Chamilo\CoreBundle\Entity', 'ChamiloCourseBundle' => 'Chamilo\CourseBundle\Entity', 'ChamiloFaqBundle' => 'Chamilo\FaqBundle\Entity' + 'ChamiloSkillBundle' => 'Chamilo\SkillBundle\Entity' ) ); diff --git a/main/inc/lib/skill.lib.php b/main/inc/lib/skill.lib.php index 2fbee4e408..0106a062a2 100755 --- a/main/inc/lib/skill.lib.php +++ b/main/inc/lib/skill.lib.php @@ -891,7 +891,7 @@ class Skill extends Model public function get_user_skills($user_id, $get_skill_data = false) { $user_id = intval($user_id); - $sql = 'SELECT DISTINCT s.id, s.name, s.icon + $sql = 'SELECT DISTINCT s.id, s.name, s.icon, u.id as issue FROM '.$this->table_skill_rel_user.' u INNER JOIN '.$this->table.' s ON u.skill_id = s.id @@ -1448,4 +1448,55 @@ class Skill extends Model return Database::store_result($result, 'ASSOC'); } + /** + * Check if the $fromUser can comment the $toUser skill issue + * @param Chamilo\UserBundle\Entity\User $fromUser + * @param Chamilo\UserBundle\Entity\User $toUser + * @return boolean + */ + public static function userCanAddFeedbackToUser($fromUser, $toUser) + { + if (api_is_platform_admin()) { + return true; + } + + $entityManager = Database::getManager(); + $userRepo = $entityManager->getRepository('ChamiloUserBundle:User'); + $fromUserStatus = $fromUser->getStatus(); + + switch ($fromUserStatus) { + case SESSIONADMIN: + if (api_get_setting('allow_session_admins_to_manage_all_sessions') === 'true') { + if ($toUser->getCreatorId() === $fromUser->getId()) { + return true; + } + } + + $sessionAdmins = $userRepo->getSessionAdmins($toUser); + + foreach ($sessionAdmins as $sessionAdmin) { + if ($sessionAdmin->getId() !== $fromUser->getId()) { + continue; + } + + return true; + } + break; + case STUDENT_BOSS: + $studentBosses = $userRepo->getStudentBosses($toUser); + + foreach ($studentBosses as $studentBoss) { + if ($studentBoss->getId() !== $fromUser->getId()) { + continue; + } + + return true; + } + case DRH: + return UserManager::is_user_followed_by_drh($toUser->getId(), $fromUser->getId()); + } + + return false; + } + } diff --git a/main/template/default/admin/skill.tpl b/main/template/default/admin/skill.tpl new file mode 100644 index 0000000000..319962a85d --- /dev/null +++ b/main/template/default/admin/skill.tpl @@ -0,0 +1,30 @@ + +

{{ 'Skills' | get_lang }}

+ + + + +{{ form }} + + + +{% for item in list %} +

{{ item.name }} ({{ item.shortCode }}) + + + +

+ {{ item.profile }} +{% endfor %} diff --git a/main/template/default/admin/skill_level.tpl b/main/template/default/admin/skill_level.tpl new file mode 100644 index 0000000000..3d63a446f2 --- /dev/null +++ b/main/template/default/admin/skill_level.tpl @@ -0,0 +1,27 @@ +{{ form }} + + + + + + + + + + {% for item in list %} + + + + + + + {% endfor %} +
{{ 'Name' | get_lang }}{{ 'ShortName' | get_lang }}{{ 'Profile' | get_lang }}{{ 'Actions' | get_lang }}
{{ item.name }}{{ item.shortName }} {{ item.profile }} + + + + + + + +
\ No newline at end of file diff --git a/main/template/default/admin/skill_profile.tpl b/main/template/default/admin/skill_profile.tpl new file mode 100644 index 0000000000..c81618e19a --- /dev/null +++ b/main/template/default/admin/skill_profile.tpl @@ -0,0 +1,42 @@ +{{ form }} + +{% for item in list %} + +

{{ item.name }} + + {##} + {##} + {##} + + + + + + + +

+ + +{% endfor %} diff --git a/main/template/default/skill/issued.tpl b/main/template/default/skill/issued.tpl index e4ab20d74b..8c5c95a0ee 100644 --- a/main/template/default/skill/issued.tpl +++ b/main/template/default/skill/issued.tpl @@ -1,79 +1,138 @@
-
-
- {{ skill_info.name }} -
-

{{ skill_info.name }}

-
-
-
-
{{ 'SkillAcquiredAt'|get_lang }}
-
- {% for course in skill_info.courses %} -

- {% if course.name %} - {{ 'TimeXThroughCourseY'|get_lang|format(course.date_issued, course.name) }} - {% else %} - {{ course.date_issued }} - {% endif %} -

- {% endfor %} -
+
+
+
+ {{ issue_info.skill_name }} +
+

{{ issue_info.skill_name }}

+ {% if issue_info.skill_short_code %} +

{{ issue_info.skill_short_code }}

+ {% endif %} +
+
+
+ {% if issue_info.skill_description %} +

{{ issue_info.skill_description }}

+ {% endif %} + {% if issue_info.skill_criteria %} +

{{ 'CriteriaToEarnTheBadge'|get_lang }}

+

{{ issue_info.skill_criteria }}

+ {% endif %}
- {% if badge_error %} -
{{ 'BakedBadgeProblem'|get_lang }}
- {% elseif personal_badge is not empty %} -

- - {{ 'DownloadBadge'|get_lang }} - -

- {% endif %} - {% if allow_export %} +
+ {% if allow_download_export %} + {% if badge_error %} +
+
{{ 'BakedBadgeProblem'|get_lang }}
+ {% else %} +

+ + {{ 'DownloadBadge'|get_lang }} + +

+ {% endif %} +

{{ 'ExportBadge'|get_lang }}

+
+
{{ 'ShareWithYourFriends' | get_lang }}
+ + + + + + +
{% endif %} -
-
{{ 'ShareWithYourFriends' | get_lang }}
- - - - - - -
-
-
-
-

{{ 'RecipientDetails'|get_lang }}

-

{{ user_info.complete_name }}

-

{{ 'BadgeDetails'|get_lang }}

-

{{ 'Name'|get_lang }}

-

{{ skill_info.name }}

- {% if skill_info.short_code %} -

{{ 'ShortCode'|get_lang }}

-

{{ skill_info.short_code }}

+
+

{{ 'RecipientDetails'|get_lang }}

+

{{ issue_info.user_complete_name }}

+

{{ 'SkillAcquiredAt'|get_lang }}

+
    +
  • + {% if issue_info.source_name %} + {{ 'TimeXThroughCourseY'|get_lang|format(issue_info.datetime, issue_info.source_name) }} + {% else %} + {{ issue_info.datetime }} + {% endif %} + {% if issue_info.argumentation %} + {% if issue_info.argumentation %} +

    {{ 'UserXIndicated'|get_lang|format(issue_info.argumentation_author_name) }}

    + {% endif %} +

    {{ issue_info.argumentation }}

    + {% endif %} +
  • +
+

{{ 'AcquiredLevel'|get_lang }}

+
    +
  • + {{ issue_info.acquired_level }} +
  • +
+ + {% if allow_comment %} +
+
+
+ {{ 'ChangeAcquiredLevel'|get_lang }} +
+
+ {{ acquired_level_form }} +
+
+
+
+
+ {{ 'XComments'|get_lang|format(issue_info.comments|length) }} + / + {{ 'AverageRatingX'|get_lang|format(issue_info.feedback_average) }} +
+
+ {{ comment_form }} +
+ {% for comment in issue_info.comments %} +
+
+

{{ comment.giver_complete_name }}

+

{{ comment.datetime }}

+

{{ comment.text }}

+
+
+
+ {% if comment.value %} + + {{ 'AverageRating' }} {{ comment.value }} + {% endif %} +
+
+
+ {% else %} +

{{ 'WithoutComment'|get_lang }}

+ {% endfor %} +
+
+ {% else %} +
+

+ {{ 'XComments'|get_lang|format(issue_info.comments|length) }} + / + {{ 'AverageRatingX'|get_lang|format(issue_info.feedback_average) }} +

{% endif %} -

{{ 'Description'|get_lang }}

-

{{ skill_info.description }}

-

{{ 'CriteriaToEarnTheBadge'|get_lang }}

-

{{ skill_info.criteria }}

-
-
-{% if allow_export %} +{% if allow_download_export %} -{% endif %} +{% endif %} \ No newline at end of file diff --git a/main/template/default/skill/issued_all.tpl b/main/template/default/skill/issued_all.tpl new file mode 100644 index 0000000000..a258133aa7 --- /dev/null +++ b/main/template/default/skill/issued_all.tpl @@ -0,0 +1,142 @@ +{% for badge in user_badges %} +
+
+
+
+ {{ badge.issue_info.skill_name }} +
+

{{ badge.issue_info.skill_name }}

+ {% if badge.issue_info.skill_short_code %} +

{{ badge.issue_info.skill_short_code }}

+ {% endif %} +
+
+
+ {% if badge.issue_info.skill_description %} +

{{ badge.issue_info.skill_description }}

+ {% endif %} + {% if badge.issue_info.skill_criteria %} +

{{ 'CriteriaToEarnTheBadge'|get_lang }}

+

{{ badge.issue_info.skill_criteria }}

+ {% endif %} +
+
+ {% if badge.allow_download_export %} + {% if badge.badge_error %} +
+
{{ 'BakedBadgeProblem'|get_lang }}
+ {% else %} +

+ + {{ 'DownloadBadge'|get_lang }} + +

+ {% endif %} +
+

+ + {{ 'ExportBadge'|get_lang }} + +

+
+
{{ 'ShareWithYourFriends' | get_lang }}
+ + + + + + +
+ {% endif %} +
+
+

{{ 'RecipientDetails'|get_lang }}

+

{{ badge.issue_info.user_complete_name }}

+

{{ 'SkillAcquiredAt'|get_lang }}

+
    +
  • + {% if badge.issue_info.source_name %} + {{ 'TimeXThroughCourseY'|get_lang|format(badge.issue_info.datetime, badge.issue_info.source_name) }} + {% else %} + {{ badge.issue_info.datetime }} + {% endif %} + {% if badge.issue_info.argumentation %} + {% if badge.issue_info.argumentation %} +

    {{ 'UserXIndicated'|get_lang|format(badge.issue_info.argumentation_author_name) }}

    + {% endif %} +

    {{ badge.issue_info.argumentation }}

    + {% endif %} +
  • +
+

{{ 'AcquiredLevel'|get_lang }}

+
    +
  • + {{ badge.issue_info.acquired_level }} +
  • +
+ + {% if badge.allow_comment %} +
+
+
+ {{ 'ChangeAcquiredLevel'|get_lang }} +
+
+ {{ badge.acquired_level_form }} +
+
+
+
+
+ {{ 'XComments'|get_lang|format(badge.issue_info.comments|length) }} + / + {{ 'AverageRatingX'|get_lang|format(badge.issue_info.feedback_average) }} +
+
+ {{ badge.comment_form }} +
+ {% for comment in badge.issue_info.comments %} +
+
+

{{ comment.giver_complete_name }}

+

{{ comment.datetime }}

+

{{ comment.text }}

+
+
+
+ {% if comment.value %} + + {{ 'AverageRating' }} {{ comment.value }} + {% endif %} +
+
+
+ {% else %} +

{{ 'WithoutComment'|get_lang }}

+ {% endfor %} +
+
+ {% else %} +
+

+ {{ 'XComments'|get_lang|format(badge.issue_info.comments|length) }} + / + {{ 'AverageRatingX'|get_lang|format(badge.issue_info.feedback_average) }} +

+ {% endif %} +
+
+ {% if badge.allow_download_export %} + + {% endif %} +
+
+{% endfor %} \ No newline at end of file diff --git a/main/template/default/social/skills_block.tpl b/main/template/default/social/skills_block.tpl index 7c66d61a83..4226139dd0 100644 --- a/main/template/default/social/skills_block.tpl +++ b/main/template/default/social/skills_block.tpl @@ -39,7 +39,7 @@