Skip to content
Snippets Groups Projects
Commit 332f5ef2 authored by Viktoria Wiebe's avatar Viktoria Wiebe Committed by Ron Lucke
Browse files

Tic 2807 - add toggling task visibility functionality to student task dashboard

Closes #2807

Merge request studip/studip!3096
parent 7a924cef
No related branches found
No related tags found
1 merge request!8UI und UX Anpassungen für #3263
<?php
class Tic2807AddCWTaskVisibility extends Migration
{
public function description()
{
return 'Adds a visibility column to courseware tasks.';
}
protected function up()
{
DBManager::get()->exec(
"ALTER TABLE `cw_tasks`
ADD COLUMN `visible` TINYINT(1) UNSIGNED NOT NULL DEFAULT 0 AFTER `renewal_date`"
);
}
protected function down()
{
DBManager::get()->exec(
"ALTER TABLE `cw_tasks`
DROP COLUMN `visible`"
);
}
}
......@@ -324,7 +324,7 @@ class Authority
public static function canShowTask(User $user, Task $resource): bool
{
return self::canUpdateTask($user, $resource);
return self::canUpdateTask($user, $resource) || $resource->visible;
}
public static function canIndexTasks(User $user): bool
......
......@@ -81,6 +81,10 @@ class TasksUpdate extends JsonApiController
$resource->requestRenewal();
}
if (self::arrayHas($json, 'data.attributes.visible')) {
$resource->setVisibility(self::arrayGet($json, 'data.attributes.visible'));
}
return $resource;
}
......
......@@ -36,6 +36,7 @@ class Task extends SchemaProvider
'submitted' => (bool) $resource['submitted'],
'renewal' => empty($resource['renewal']) ? null : (string) $resource['renewal'],
'renewal-date' => date('c', $resource['renewal_date']),
'visible' => (bool) $resource['visible'],
'mkdate' => date('c', $resource['mkdate']),
'chdate' => date('c', $resource['chdate']),
];
......
......@@ -391,6 +391,19 @@ class StructuralElement extends \SimpleORMap implements \PrivacyObject, \Feedbac
return true;
}
if ($task->isSubmitted()) {
if ($task->visible) {
return true;
}
$solvers = $task->getTaskGroup()->getSolvers();
foreach ($solvers as $solver) {
if ($solver->id === $user->id) {
return true;
}
}
return false;
}
return $task->userIsASolver($user);
}
......@@ -1240,4 +1253,9 @@ SQL;
[$this->id, self::class]
);
}
public function isTaskVisible(): bool
{
return $this->payload['task-visibility'];
}
}
......@@ -21,6 +21,7 @@ use User;
* @property int $submitted database column
* @property string|null $renewal database column
* @property int $renewal_date database column
* @property int $visible database column
* @property int|null $feedback_id database column
* @property int $mkdate database column
* @property int $chdate database column
......@@ -90,6 +91,11 @@ class Task extends \SimpleORMap
parent::configure($config);
}
public function getTaskGroup(): TaskGroup
{
return $this->task_group;
}
/**
* Returns the structural element of this task.
* This structural element and all its children are part of the task.
......@@ -130,6 +136,16 @@ class Task extends \SimpleORMap
if ($this->solver_id === $user->id) {
return true;
}
if ($this->visible) {
$solvers = $this->getTaskGroup()->getSolvers();
foreach ($solvers as $solver) {
if ($solver->id === $user->id) {
return true;
}
}
}
break;
case 'group':
......@@ -235,6 +251,12 @@ class Task extends \SimpleORMap
$this->store();
}
public function setVisibility(bool $visibility): void
{
$this->visible = (int) $visibility;
$this->store();
}
private function getStructuralElementProgress(StructuralElement $structural_element): float
{
$containers = Container::findBySQL('structural_element_id = ?', [intval($structural_element->id)]);
......
......@@ -2,7 +2,15 @@
<div class="cw-dashboard-tasks-wrapper">
<table v-if="tasks.length > 0" class="default">
<colgroup>
<col />
<col style="width: 5%" />
<col style="width: 20%" />
<col style="width: 10%" />
<col style="width: 10%" />
<col style="width: 5%" />
<col style="width: 15%" />
<col style="width: 15%" />
<col style="width: 15%" />
<col style="width: 5%" />
</colgroup>
<thead>
<tr>
......@@ -12,6 +20,7 @@
<th>{{ $gettext('Abgabefrist') }}</th>
<th>{{ $gettext('Abgabe') }}</th>
<th class="responsive-hidden">{{ $gettext('Verlängerungsanfrage') }}</th>
<th class="responsive-hidden">{{ $gettext('Für Teilnehmende freigeben') }}</th>
<th class="responsive-hidden">{{ $gettext('Anmerkung') }}</th>
<th class="actions">{{ $gettext('Aktionen') }}</th>
</tr>
......@@ -54,6 +63,23 @@
{{ $gettext('verlängert bis') }}: {{ getReadableDate(task.attributes['renewal-date']) }}
</span>
</td>
<td class="responsive-hidden">
<span v-if="task.attributes.submitted">
<button
class="button"
v-if="!task.attributes.visible"
@click="toggleVisibilityOn(task)"
>
{{ $gettext('Freigeben') }}
</button>
<button
class="button"
v-if="task.attributes.visible"
@click="toggleVisibilityOff(task)">
{{ $gettext('Freigabe widerrufen') }}
</button>
</span>
</td>
<td class="responsive-hidden">
<studip-icon
v-if="feedback"
......@@ -166,6 +192,13 @@ export default {
return result;
});
},
taskVisibilities() {
let visibilities = [];
for (const task of this.tasks) {
visibilities[`${task.task.id}`] = task.element.attributes.payload['task-visibility'];
}
return visibilities;
}
},
methods: {
...mapActions({
......@@ -175,6 +208,7 @@ export default {
companionSuccess: 'companionSuccess',
companionError: 'companionError',
createCoursewareUnit: 'courseware-units/create',
loadStructuralElement: 'courseware-structural-elements/loadById'
}),
getTaskMenuItems(task, status, element) {
let menuItems = [];
......@@ -277,6 +311,37 @@ export default {
this.showFeedbackDialog = true;
this.currentTaskFeedback = feedback.attributes.content;
},
toggleVisibilityOn(task) {
let attributes = task.attributes;
attributes['visible'] = true;
this.toggleVisibility(task, attributes);
},
toggleVisibilityOff(task) {
let attributes = task.attributes;
attributes['visible'] = false;
this.toggleVisibility(task, attributes);
},
async toggleVisibility(task, attributes) {
await this.updateTask({
attributes: attributes,
taskId: task.id,
});
const taskGroup = this.getTaskGroupById({ id: task.relationships['task-group'].data.id });
const taskTitle = taskGroup.attributes.title;
if (attributes.visible) {
this.companionSuccess({
info: this.$gettextInterpolate(this.$gettext('"%{ title }" wurde freigegeben.'),
{ title: taskTitle }),
});
} else {
this.companionSuccess({
info: this.$gettextInterpolate(this.$gettext('Die Freigabe für %{ "title }" wurde zurückgenommen.'),
{ title: taskTitle }),
});
}
}
},
};
</script>
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment