Commit 0094d7e5 authored by mathieso's avatar mathieso

Recover from Git crash, maybe. Computers suck.

parent f70e483d
......@@ -8,7 +8,7 @@ dependencies:
id: classselector_2
theme: skilling_bootstrap
region: sidebar_first
weight: -5
weight: -7
provider: null
plugin: class_selector
settings:
......
......@@ -9,7 +9,7 @@ dependencies:
id: suggestion
theme: skilling_bootstrap
region: sidebar_first
weight: -3
weight: -5
provider: null
plugin: suggestion_block
settings:
......
......@@ -29,7 +29,7 @@ display:
position: 0
display_options:
access:
type: InstructorAccess
type: InstructorGraderAccess
options: { }
cache:
type: none
......
......@@ -427,7 +427,7 @@ display:
exclude: false
alter:
alter_text: true
text: "<a href=\"{{ path('<front>') }}admin/skilling/enrollments/list/{{ nid }}\">Enrollments</a><br>\r\n\r\n<a href=\"{{ path('<front>') }}admin/skilling/class-progress/{{ nid }}\">Progress</a><br>\r\n\r\n<a href=\"{{ path('<front>') }}node/{{ nid }}/edit\">Edit</a>"
text: "ROSIE!!\r\n\r\n<a href=\"{{ path('<front>') }}admin/skilling/enrollments/list/{{ nid }}\">Enrollments</a><br>\r\n\r\n<a href=\"{{ path('<front>') }}admin/skilling/submissions-for-class/list/{{ nid }}\">Submissions</a><br>\r\n\r\n<a href=\"{{ path('<front>') }}admin/skilling/class-progress/{{ nid }}\">Progress</a><br>\r\n\r\n<a href=\"{{ path('<front>') }}node/{{ nid }}/edit\">Edit</a>"
make_link: false
path: ''
absolute: false
......@@ -626,16 +626,7 @@ display:
plugin_id: text_custom
footer: { }
empty: { }
relationships:
field_calendar:
id: field_calendar
table: node__field_calendar
field: field_calendar
relationship: none
group_type: group
admin_label: 'Class calendar'
required: false
plugin_id: standard
relationships: { }
arguments: { }
display_extenders: { }
filter_groups:
......
......@@ -90,7 +90,7 @@ display:
group_type: group
admin_label: ''
label: ID
exclude: false
exclude: true
alter:
alter_text: false
text: ''
......@@ -269,7 +269,7 @@ display:
exclude: false
alter:
alter_text: true
text: '{{ field_rubric_item_responses }} {{ field_rubric_item_responses__target_id }}'
text: '{{ field_rubric_item_responses }}'
make_link: false
path: ''
absolute: false
......
......@@ -71,11 +71,29 @@ display:
summary: ''
description: ''
columns:
exercise_nid: exercise_nid
where_referenced: where_referenced
when_first_submission: when_first_submission
exercise_title: exercise_title
completed: completed
exercise_due_date: exercise_due_date
exercise_max_subs: exercise_max_subs
status: status
submissions: submissions
info:
exercise_nid:
sortable: false
default_sort_order: asc
align: ''
separator: ''
empty_column: false
responsive: ''
where_referenced:
sortable: false
default_sort_order: asc
align: ''
separator: ''
empty_column: false
responsive: ''
when_first_submission:
sortable: true
default_sort_order: desc
......@@ -90,7 +108,21 @@ display:
separator: ''
empty_column: false
responsive: ''
completed:
exercise_due_date:
sortable: true
default_sort_order: asc
align: ''
separator: ''
empty_column: false
responsive: ''
exercise_max_subs:
sortable: false
default_sort_order: asc
align: ''
separator: ''
empty_column: false
responsive: ''
status:
sortable: false
default_sort_order: asc
align: ''
......@@ -114,6 +146,63 @@ display:
hide_empty: false
default_field_elements: true
fields:
exercise_nid:
id: exercise_nid
table: student_submissions
field: exercise_nid
relationship: none
group_type: group
admin_label: ''
label: 'Exercise id'
exclude: true
alter:
alter_text: false
text: ''
make_link: false
path: ''
absolute: false
external: false
replace_spaces: false
path_case: none
trim_whitespace: false
alt: ''
rel: ''
link_class: ''
prefix: ''
suffix: ''
target: ''
nl2br: false
max_length: 0
word_boundary: true
ellipsis: true
more_link: false
more_link_text: ''
more_link_path: ''
strip_tags: false
trim: false
preserve_tags: ''
html: false
element_type: ''
element_class: ''
element_label_type: ''
element_label_class: ''
element_label_colon: true
element_wrapper_type: ''
element_wrapper_class: ''
element_default_classes: true
empty: ''
hide_empty: false
empty_zero: false
hide_alter_empty: true
set_precision: false
precision: 0
decimal: .
separator: ','
format_plural: false
format_plural_string: !!binary MQNAY291bnQ=
prefix: ''
suffix: ''
plugin_id: numeric
where_referenced:
id: where_referenced
table: student_submissions
......@@ -226,7 +315,108 @@ display:
exclude: false
alter:
alter_text: true
text: "{{ exercise_title }}<br>\n{{ where_referenced }}"
text: "<a href=\"{{ path('entity.node.canonical', {'node': exercise_nid}) }}\">{{ exercise_title }}</a><br>\r\n{{ where_referenced }}"
make_link: false
path: ''
absolute: false
external: false
replace_spaces: false
path_case: none
trim_whitespace: false
alt: ''
rel: ''
link_class: ''
prefix: ''
suffix: ''
target: ''
nl2br: false
max_length: 0
word_boundary: true
ellipsis: true
more_link: false
more_link_text: ''
more_link_path: ''
strip_tags: false
trim: false
preserve_tags: ''
html: false
element_type: ''
element_class: ''
element_label_type: ''
element_label_class: ''
element_label_colon: true
element_wrapper_type: ''
element_wrapper_class: ''
element_default_classes: true
empty: ''
hide_empty: false
empty_zero: false
hide_alter_empty: true
plugin_id: standard
exercise_due_date:
id: exercise_due_date
table: student_submissions
field: exercise_due_date
relationship: none
group_type: group
admin_label: ''
label: 'Due date'
exclude: false
alter:
alter_text: false
text: ''
make_link: false
path: ''
absolute: false
external: false
replace_spaces: false
path_case: none
trim_whitespace: false
alt: ''
rel: ''
link_class: ''
prefix: ''
suffix: ''
target: ''
nl2br: false
max_length: 0
word_boundary: true
ellipsis: true
more_link: false
more_link_text: ''
more_link_path: ''
strip_tags: false
trim: false
preserve_tags: ''
html: false
element_type: ''
element_class: ''
element_label_type: ''
element_label_class: ''
element_label_colon: true
element_wrapper_type: ''
element_wrapper_class: ''
element_default_classes: true
empty: ''
hide_empty: false
empty_zero: false
hide_alter_empty: true
date_format: trimmed_date
custom_date_format: ''
timezone: ''
plugin_id: date
exercise_max_subs:
id: exercise_max_subs
table: student_submissions
field: exercise_max_subs
relationship: none
group_type: group
admin_label: ''
label: 'Max submissions'
exclude: false
alter:
alter_text: false
text: ''
make_link: false
path: ''
absolute: false
......@@ -417,7 +607,7 @@ display:
relationship: none
group_type: group
admin_label: ''
empty: false
empty: true
tokenize: false
content:
value: '<h4>Report</h4>'
......
......@@ -14,6 +14,7 @@ dependencies:
module:
- datetime
- node
- skilling
- text
- user
id: submissions_administration
......@@ -37,7 +38,7 @@ display:
instructor: instructor
administrator: administrator
cache:
type: tag
type: none
options: { }
query:
type: views_query
......@@ -1220,6 +1221,84 @@ display:
entity_type: node
entity_field: created
plugin_id: date
instructor_of_node_owner_filter:
id: instructor_of_node_owner_filter
table: node_field_data
field: instructor_of_node_owner_filter
relationship: none
group_type: group
admin_label: ''
operator: '='
value: '1'
group: 1
exposed: false
expose:
operator_id: ''
label: ''
description: ''
use_operator: false
operator: ''
operator_limit_selection: false
operator_list: { }
identifier: ''
required: false
remember: false
multiple: false
remember_roles:
authenticated: authenticated
is_grouped: false
group_info:
label: ''
description: ''
identifier: ''
optional: true
widget: select
multiple: false
remember: false
default_group: All
default_group_multiple: { }
group_items: { }
entity_type: node
plugin_id: instructor_of_node_owner_filter
node_owner_student_in_class_filter:
id: node_owner_student_in_class_filter
table: node_field_data
field: node_owner_student_in_class_filter
relationship: none
group_type: group
admin_label: ''
operator: '='
value: '1'
group: 1
exposed: false
expose:
operator_id: ''
label: ''
description: ''
use_operator: false
operator: ''
operator_limit_selection: false
operator_list: { }
identifier: ''
required: false
remember: false
multiple: false
remember_roles:
authenticated: authenticated
is_grouped: false
group_info:
label: ''
description: ''
identifier: ''
optional: true
widget: select
multiple: false
remember: false
default_group: All
default_group_multiple: { }
group_items: { }
entity_type: node
plugin_id: node_owner_student_in_class_filter
sorts: { }
title: 'Submissions administration'
header:
......
......@@ -22020,7 +22020,7 @@ module.exports={render:function (){var _vm=this;var _h=_vm.$createElement;var _c
attrs: {
"for": 'cat' + category.categoryId
}
}, [_vm._v("\r\n " + _vm._s(category.name) + "\r\n ")])])
}, [_vm._v("\n " + _vm._s(category.name) + "\n ")])])
})], 2), _vm._v(" "), _c('div', {
attrs: {
"id": "rubric-item-list"
......@@ -22037,8 +22037,8 @@ module.exports={render:function (){var _vm=this;var _h=_vm.$createElement;var _c
on: {
"click": _vm.rubricItemClick
}
}, [_vm._v("\r\n " + _vm._s(rubricItem.name) + "\r\n ")])
}), 0) : _c('p', [_vm._v("\r\n No items matching your category choices that are not already\r\n attached to the exercise.\r\n ")])])]), _vm._v(" "), _c('div', {
}, [_vm._v("\n " + _vm._s(rubricItem.name) + "\n ")])
}), 0) : _c('p', [_vm._v("\n No items matching your category choices that are not already\n attached to the exercise.\n ")])])]), _vm._v(" "), _c('div', {
attrs: {
"id": "footer"
}
......@@ -22256,7 +22256,7 @@ module.exports={render:function (){var _vm=this;var _h=_vm.$createElement;var _c
attrs: {
"id": "rubric-item-name-help"
}
}, [_vm._v("\r\n E.g., Variable naming\r\n ")])])]), _vm._v(" "), _c('div', {
}, [_vm._v("\n E.g., Variable naming\n ")])])]), _vm._v(" "), _c('div', {
staticClass: "form-group",
attrs: {
"id": "categories-container"
......@@ -22289,7 +22289,7 @@ module.exports={render:function (){var _vm=this;var _h=_vm.$createElement;var _c
attrs: {
"for": category.categoryId
}
}, [_vm._v("\r\n " + _vm._s(category.name) + "\r\n ")])])
}, [_vm._v("\n " + _vm._s(category.name) + "\n ")])])
})], 2), _vm._v(" "), _c('div', {
staticClass: "form-group",
attrs: {
......
......@@ -24,10 +24,10 @@ services:
arguments: []
tags:
- { name: twig.extension }
# skilling.route_subscriber:
# class: Drupal\skilling\Routing\RouteSubscriber
# tags:
# - { name: event_subscriber }
# skilling.route_subscriber:
# class: Drupal\skilling\Routing\RouteSubscriber
# tags:
# - { name: event_subscriber }
#Check whether the current user has instructor or admin role.
#Used in, e.g., enrollment management view, as an extra route-level check.
skilling.instructor_check:
......@@ -38,10 +38,10 @@ services:
skilling.completion_score:
class: Drupal\skilling\CompletionScore
arguments: ['@entity_type.manager', '@skilling.utilities', '@skilling.skilling_user_factory', '@skilling.skilling_current_user', '@skilling.current_class', '@skilling.enrollment', '@messenger']
# #Logger channel.
# skilling.logger.channel:
# parent: logger.channel_base
# arguments: ['skilling']
# #Logger channel.
# skilling.logger.channel:
# parent: logger.channel_base
# arguments: ['skilling']
skilling.starter.make_nodes:
class: Drupal\skilling\MakeStarterContent\MakeNodes
arguments: ['@entity_type.manager', '@book.manager', '@skilling.utilities', '@file_system', '@entity_field.manager']
......@@ -65,7 +65,7 @@ services:
arguments: ['@entity_type.manager', '@skilling.skilling_current_user', '@skilling.current_class', '@skilling.check_user_relationships', '@config.factory', '@skilling.skilling_user_factory', '@skilling.utilities', '@skilling.skillingparser', '@messenger', '@skilling.field_access_special_case_checker']
skilling.check_user_relationships:
class: Drupal\skilling\Access\SkillingCheckUserRelationships
arguments: ['@skilling.utilities', '@skilling.skilling_user_factory']
arguments: ['@entity_type.manager', '@skilling.utilities', '@skilling.skilling_user_factory']
skilling.assessment:
class: Drupal\skilling\Assessment
arguments: ['@entity_type.manager', '@skilling.skilling_current_user', '@skilling.utilities', '@date.formatter', '@renderer']
......
......@@ -49,7 +49,7 @@ function skilling_views_data_alter(&$data) {
];
$data['node__field_when_read']['unread_filter'] = array(
// $data['node_field_data']['unread_filter'] = array(
// $data['node_field_data']['unread_filter'] = array(
'filter' => [
'title' => t('Notices to show'),
'help' => t('Only show unread notices, or show all?'),
......@@ -69,6 +69,26 @@ function skilling_views_data_alter(&$data) {
],
);
$data['node_field_data']['instructor_of_node_owner_in_class_filter'] = array(
'filter' => [
'title' => t('Current user instructor of node owner in class from URL'),
'help' => t('Is the current user an instructor of the node owner in the class with the id given as the last argument of the URL?'),
'field' => 'instructor_of_node_owner_in_class_filter',
'id' => 'instructor_of_node_owner_in_class_filter',
'group' => 'Skilling',
],
);
$data['node_field_data']['node_owner_student_in_class_filter'] = array(
'filter' => [
'title' => t('Node owner is student in class from URL'),
'help' => t('Is the node owner a student in the class with the id given as the last argument of the URL?'),
'field' => 'node_owner_student_in_class_filter',
'id' => 'node_owner_student_in_class_filter',
'group' => 'Skilling',
],
);
// For query plugin giving data on one student's exercise submissions.
$data['student_submissions']['table']['group'] = t("Student's submissions");
......
......@@ -2,6 +2,9 @@
namespace Drupal\skilling\Access;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\skilling\SkillingClass;
use Drupal\skilling\SkillingConstants;
use Drupal\skilling\SkillingUser;
use Drupal\skilling\SkillingUserFactory;
......@@ -18,6 +21,13 @@ use Drupal\skilling\Utilities as SkillingUtilities;
*/
class SkillingCheckUserRelationships {
/**
* The entity type manager service.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* The Skilling utilities service.
*
......@@ -35,12 +45,19 @@ class SkillingCheckUserRelationships {
/**
* SkillingCheckUserRelationships constructor.
*
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
* The entity type manager service.
* @param \Drupal\skilling\Utilities $skillingUtilities
* The Skilling utilities service.
* @param \Drupal\skilling\SkillingUserFactory $userFactory
* The user factory service.
*/
public function __construct(SkillingUtilities $skillingUtilities, SkillingUserFactory $userFactory) {
public function __construct(
EntityTypeManagerInterface $entityTypeManager,
SkillingUtilities $skillingUtilities,
SkillingUserFactory $userFactory
) {
$this->entityTypeManager = $entityTypeManager;
$this->skillingUtilities = $skillingUtilities;
$this->userFactory = $userFactory;
}
......@@ -101,38 +118,41 @@ class SkillingCheckUserRelationships {
if (!$possibleStudent->isStudent()) {
return FALSE;
}
// Get enrollments of possible instructor.
$possibleInstructorEnrollments
= $this->skillingUtilities->getUserEnrollmentsPublished($possibleInstructor->id());
// Find class nids for which the user is an instructor.
$instructorClassNids = [];
foreach ($possibleInstructorEnrollments as $possibleInstructorEnrollment) {
$classSpecificRoles = $possibleInstructorEnrollment->field_class_roles->getValue();
foreach ($classSpecificRoles as $key => $value) {
$classRole = $value['value'];
if ($classRole === SkillingConstants::CLASS_ROLE_INSTRUCTOR) {
$instructorClassNids[] = $possibleInstructorEnrollment->field_class->target_id;
}
}
}
// Get class nids the user teaches.
$instructorClassNids = $this->getInstructorClassIds($possibleInstructor);
// // Get enrollments of possible instructor.
// $possibleInstructorEnrollments
// = $this->skillingUtilities->getUserEnrollmentsPublished($possibleInstructor->id());
// // Find class nids for which the user is an instructor.
// $instructorClassNids = [];
// foreach ($possibleInstructorEnrollments as $possibleInstructorEnrollment) {
// $classSpecificRoles = $possibleInstructorEnrollment->field_class_roles->getValue();
// foreach ($classSpecificRoles as $key => $value) {
// $classRole = $value['value'];
// if ($classRole === SkillingConstants::CLASS_ROLE_INSTRUCTOR) {
// $instructorClassNids[] = $possibleInstructorEnrollment->field_class->target_id;
// }
// }
// }
// Instructor of any classes?
if (count($instructorClassNids) === 0) {
return FALSE;
}
// Get the enrollments of the possible student.
$possibleStudentEnrollments
= $this->skillingUtilities->getUserEnrollmentsPublished($possibleStudent->id());
// Find class nids for which the user is an instructor.
$studentClassNids = [];
foreach ($possibleStudentEnrollments as $possibleStudentEnrollment) {
$classSpecificRoles = $possibleStudentEnrollment->field_class_roles->getValue();
foreach ($classSpecificRoles as $key => $value) {
$classRole = $value['value'];
if ($classRole === SkillingConstants::CLASS_ROLE_STUDENT) {
$studentClassNids[] = $possibleStudentEnrollment->field_class->target_id;
}
}
}
$studentClassNids = $this->getStudentClassIds($possibleStudent);
// $possibleStudentEnrollments
// = $this->skillingUtilities->getUserEnrollmentsPublished($possibleStudent->id());
// // Find class nids for which the user is an instructor.
// $studentClassNids = [];
// foreach ($possibleStudentEnrollments as $possibleStudentEnrollment) {
// $classSpecificRoles = $possibleStudentEnrollment->field_class_roles->getValue();
// foreach ($classSpecificRoles as $key => $value) {
// $classRole = $value['value'];
// if ($classRole === SkillingConstants::CLASS_ROLE_STUDENT) {
// $studentClassNids[] = $possibleStudentEnrollment->field_class->target_id;
// }
// }
// }
// Student in any classes?
if (count($studentClassNids) === 0) {
return FALSE;
......@@ -142,6 +162,118 @@ class SkillingCheckUserRelationships {
return count($commonClassNids) > 0;
}
/**
* @param \Drupal\skilling\SkillingUser $user
* @param \Drupal\node\EntityInterface $class
*
* @return bool
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
*/
public function isInstructorOfClass(SkillingUser $user, EntityInterface $class) {
$userClasseIds = $this->getInstructorClassIds($user);
$classId = $class->id();
$result = in_array($classId, $userClasseIds);
return $result;
}
/**
* @param $userId
* @param $classId
*
* @return bool
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
* @throws \Drupal\skilling\Exception\SkillingException
*/
public function isInstructorIdOfClassId($userId, $classId) {
$user = $this->userFactory->makeSkillingUser($userId);
if (!$user) {
return FALSE;
}
$class = $this->entityTypeManager->getStorage('node')
->load($classId);
if (!$class) {
return FALSE;
}