Skip to content

Commit

Permalink
[Training] Improved cursus (#2834)
Browse files Browse the repository at this point in the history
* New editor cursus

* archive and restore actions

* Creation types for trainings

* hidden archived session and event

* PR review

* pr review 2
  • Loading branch information
WolfyWin authored Sep 4, 2024
1 parent d7de07a commit 6ce83d0
Show file tree
Hide file tree
Showing 49 changed files with 1,316 additions and 138 deletions.
93 changes: 85 additions & 8 deletions src/plugin/cursus/Controller/CourseController.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public function __construct(
RoutingHelper $routing,
ToolManager $toolManager,
CourseManager $manager,
PdfManager $pdfManager
PdfManager $pdfManager,
) {
$this->authorization = $authorization;
$this->tokenStorage = $tokenStorage;
Expand Down Expand Up @@ -106,6 +106,8 @@ protected function getDefaultHiddenFilters(): array
}
}

$filters['archived'] = false;

return $filters;
}

Expand All @@ -114,14 +116,89 @@ protected function getDefaultHiddenFilters(): array
*/
public function listPublicAction(Request $request): JsonResponse
{
$params = $request->query->all();
$params['hiddenFilters'] = [
'public' => true,
];
return new JsonResponse($this->crud->list(
Course::class,
array_merge($request->query->all(), ['hiddenFilters' => array_merge($this->getDefaultHiddenFilters(), [
'public' => true,
])]),
$this->getOptions()['list']
));
}

return new JsonResponse(
$this->crud->list(Course::class, $params)
);
/**
* @Route("/list/archived", name="apiv2_cursus_course_list_archived", methods={"GET"})
*/
public function listArchivedAction(Request $request): JsonResponse
{
$this->checkPermission('IS_AUTHENTICATED_FULLY', null, [], true);

return new JsonResponse($this->crud->list(
Course::class,
array_merge($request->query->all(), ['hiddenFilters' => array_merge($this->getDefaultHiddenFilters(), [
'archived' => true,
])]),
$this->getOptions()['list']
));
}

/**
* @Route("/archive", name="apiv2_cursus_course_archive", methods={"POST"})
*/
public function archiveAction(Request $request): JsonResponse
{
$processed = [];

$this->om->startFlushSuite();

$data = json_decode($request->getContent(), true);

/** @var Course[] $courses */
$courses = $this->om->getRepository(Course::class)->findBy([
'uuid' => $data['ids'],
]);

foreach ($courses as $course) {
if ($this->authorization->isGranted('ADMINISTRATE', $course) && !$course->isArchived()) {
$course->setArchived(true);
$processed[] = $course;
}
}

$this->om->endFlushSuite();

return new JsonResponse(array_map(function (Course $course) {
return $this->serializer->serialize($course);
}, $processed));
}

/**
* @Route("/restore", name="apiv2_cursus_course_restore", methods={"POST"})
*/
public function restoreAction(Request $request): JsonResponse
{
$processed = [];

$this->om->startFlushSuite();

$data = json_decode($request->getContent(), true);

/** @var Course[] $courses */
$courses = $this->om->getRepository(Course::class)->findBy([
'uuid' => $data['ids'],
]);

foreach ($courses as $course) {
if ($this->authorization->isGranted('ADMINISTRATE', $course) && $course->isArchived()) {
$course->setArchived(false);
$processed[] = $course;
}
}

$this->om->endFlushSuite();

return new JsonResponse(array_map(function (Course $course) {
return $this->serializer->serialize($course);
}, $processed));
}

/**
Expand Down
2 changes: 2 additions & 0 deletions src/plugin/cursus/Entity/Course.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

namespace Claroline\CursusBundle\Entity;

use Claroline\AppBundle\Entity\Meta\Archived;
use Claroline\AppBundle\Entity\Meta\IsPublic;
use Claroline\CommunityBundle\Model\HasOrganizations;
use Claroline\CoreBundle\Entity\Facet\PanelFacet;
Expand All @@ -31,6 +32,7 @@ class Course extends AbstractTraining
{
use HasOrganizations;
use IsPublic;
use Archived;

/**
* @Gedmo\Slug(fields={"name"})
Expand Down
1 change: 1 addition & 0 deletions src/plugin/cursus/Finder/EventFinder.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public function configureQueryBuilder(QueryBuilder $qb, array $searches = [], ar
$qb->join('obj.plannedObject', 'po');
$qb->join('obj.session', 's');
$qb->join('s.course', 'c');
$qb->andWhere('c.archived = 0');

foreach ($searches as $filterName => $filterValue) {
switch ($filterName) {
Expand Down
1 change: 1 addition & 0 deletions src/plugin/cursus/Finder/SessionFinder.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public static function getClass(): string
public function configureQueryBuilder(QueryBuilder $qb, array $searches = [], array $sortBy = null, ?int $page = 0, ?int $limit = -1): QueryBuilder
{
$qb->join('obj.course', 'c');
$qb->andWhere('c.archived = 0');

foreach ($searches as $filterName => $filterValue) {
switch ($filterName) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace Claroline\CursusBundle\Installation\Migrations;

use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;

/**
* Auto-generated migration based on mapping information: modify it with caution.
*
* Generation date: 2024/08/21 01:00:17
*/
final class Version20240821130015 extends AbstractMigration
{
public function up(Schema $schema): void
{
$this->addSql('
ALTER TABLE claro_cursusbundle_course
ADD archived TINYINT(1) NOT NULL
');
}

public function down(Schema $schema): void
{
$this->addSql('
ALTER TABLE claro_cursusbundle_course
DROP archived
');
}
}
53 changes: 53 additions & 0 deletions src/plugin/cursus/Resources/modules/actions/course/archive.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import {createElement} from 'react'
import get from 'lodash/get'

import {url} from '#/main/app/api'
import {ASYNC_BUTTON} from '#/main/app/buttons'
import {hasPermission} from '#/main/app/security'
import {trans, transChoice} from '#/main/app/intl/translation'

import {CourseCard} from '#/plugin/cursus/course/components/card'

/**
* Archive action.
*/
export default (courses, refresher) => {
const processable = courses.filter(course => hasPermission('administrate', course) && !get(course, 'meta.archived'))

return {
name: 'archive',
type: ASYNC_BUTTON,
icon: 'fa fa-fw fa-box',
label: trans('archive', {}, 'actions'),
displayed: 0 !== processable.length,
dangerous: true,
confirm: {
title: transChoice('archive_training_confirm_title', processable.length, {}, 'actions'),
message: transChoice('archive_training_confirm_message', processable.length, {count: processable.length}, 'actions'),
additional: [
createElement('div', {
key: 'additional',
className: 'modal-body'
}, processable.map(course => createElement(CourseCard, {
key: course.id,
orientation: 'row',
className: 'mb-2',
size: 'xs',
data: course
})))
]
},
request: {
url: url(['apiv2_cursus_course_archive']),
request: {
method: 'POST',
body: JSON.stringify({
ids: processable.map(course => course.id)
})
},
success: (response) => refresher.update(response)
},
group: trans('management'),
scope: ['object', 'collection']
}
}
34 changes: 34 additions & 0 deletions src/plugin/cursus/Resources/modules/actions/course/restore.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import get from 'lodash/get'

import {url} from '#/main/app/api'
import {ASYNC_BUTTON} from '#/main/app/buttons'
import {trans} from '#/main/app/intl/translation'
import {hasPermission} from '#/main/app/security'

/**
* Restore action.
*/
export default (courses, refresher) => {
const processable = courses.filter(course => hasPermission('administrate', course) && get(course, 'meta.archived'))

return {
name: 'restore',
type: ASYNC_BUTTON,
icon: 'fa fa-fw fa-box-open',
label: trans('restore', {}, 'actions'),
displayed: 0 !== processable.length,
request: {
url: url(['apiv2_cursus_course_restore']),
request: {
method: 'POST',
body: JSON.stringify({
ids: processable.map(course => course.id)
})
},
success: (response) => refresher.update(response)
},
group: trans('management'),
scope: ['object', 'collection'],
dangerous: true
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,13 @@ const CourseAbout = (props) => {
</div>

<div className="col-md-9">

{get(props.course, 'meta.archived') === true &&
<AlertBlock type="info" title={trans('course_archived_info', {}, 'cursus')}>
{trans('course_archived_info_help', {}, 'cursus')}
</AlertBlock>
}

{!isEmpty(props.activeSession) &&
<div className="content-resume">
<div className="content-resume-info content-resume-primary">
Expand Down
50 changes: 0 additions & 50 deletions src/plugin/cursus/Resources/modules/course/components/edit.jsx

This file was deleted.

26 changes: 14 additions & 12 deletions src/plugin/cursus/Resources/modules/course/components/empty.jsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,27 @@
import React from 'react'
import {PropTypes as T} from 'prop-types'

import {trans} from '#/main/app/intl/translation'
import {LINK_BUTTON} from '#/main/app/buttons'
import {ToolPage} from '#/main/core/tool'
import {Button} from '#/main/app/action/components/button'
import {MODAL_BUTTON} from '#/main/app/buttons'
import {trans} from '#/main/app/intl/translation'

import {ContentSizing} from '#/main/app/content/components/sizing'
import {CreationType} from '#/plugin/cursus/course/components/type'
import {ContentPlaceholder} from '#/main/app/content/components/placeholder'
import {MODAL_COURSE_TYPE_CREATION} from '#/plugin/cursus/course/modals/creation'

const EmptyCourse = (props) =>
<ToolPage
primaryAction="add"
actions={[
{
name: 'add',
type: LINK_BUTTON,
type: MODAL_BUTTON,
icon: 'fa fa-fw fa-plus',
label: trans('add_course', {}, 'cursus'),
target: `${props.path}/new`,
modal: [MODAL_COURSE_TYPE_CREATION, {
path: props.path
}],
group: trans('management'),
displayed: props.canEdit,
primary: true
Expand All @@ -30,14 +34,12 @@ const EmptyCourse = (props) =>
title={trans('no_course', {}, 'cursus')}
help={trans('no_course_help', {}, 'cursus')}
/>
<Button
className="btn btn-primary w-100 my-3"
size="lg"
type={LINK_BUTTON}
target={`${props.path}/new`}
label={trans('add_course', {}, 'cursus')}
/>
</ContentSizing>

<ContentSizing size="md" className="mt-4">
<CreationType {...props} />
</ContentSizing>

</ToolPage>

EmptyCourse.propTypes = {
Expand Down
Loading

0 comments on commit 6ce83d0

Please sign in to comment.