Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Cursus] copy action #2850

Merged
merged 11 commits into from
Sep 13, 2024
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/main/core/Entity/Planning/PlannedObject.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
use Doctrine\ORM\Mapping as ORM;

/**
* @ORM\Entity()
* @ORM\Entity(repositoryClass="Claroline\CoreBundle\Repository\Planning\PlannedObjectRepository")
*
* @ORM\Table(name="claro_planned_object")
*/
class PlannedObject
Expand Down Expand Up @@ -74,6 +75,7 @@ class PlannedObject

/**
* @ORM\ManyToOne(targetEntity="Claroline\CoreBundle\Entity\Location")
*
* @ORM\JoinColumn(name="location_id", nullable=true, onDelete="SET NULL")
*/
private ?Location $location = null;
Expand Down
20 changes: 20 additions & 0 deletions src/main/core/Repository/Planning/PlannedObjectRepository.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

/*
* This file is part of the Claroline Connect package.
*
* (c) Claroline Consortium <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Claroline\CoreBundle\Repository\Planning;

use Claroline\AppBundle\Repository\UniqueValueFinder;
use Doctrine\ORM\EntityRepository;

class PlannedObjectRepository extends EntityRepository
{
use UniqueValueFinder;
}
3 changes: 3 additions & 0 deletions src/main/core/Repository/Planning/PlanningRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,14 @@

namespace Claroline\CoreBundle\Repository\Planning;

use Claroline\AppBundle\Repository\UniqueValueFinder;
use Claroline\CoreBundle\Library\Normalizer\DateNormalizer;
use Doctrine\ORM\EntityRepository;

class PlanningRepository extends EntityRepository
{
use UniqueValueFinder;
WolfyWin marked this conversation as resolved.
Show resolved Hide resolved

public function areDatesAvailable(string $objectId, \DateTimeInterface $start, \DateTimeInterface $end): bool
{
$count = (int) $this->getEntityManager()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@

namespace Claroline\CoreBundle\Subscriber\Crud\Planning;

use Claroline\AppBundle\Event\Crud\CopyEvent;
use Claroline\AppBundle\Event\Crud\CreateEvent;
use Claroline\AppBundle\Event\Crud\DeleteEvent;
use Claroline\AppBundle\Event\Crud\UpdateEvent;
use Claroline\AppBundle\Event\CrudEvents;
use Claroline\AppBundle\Persistence\ObjectManager;
use Claroline\CoreBundle\Entity\Location;
use Claroline\CoreBundle\Entity\Planning\AbstractPlanned;
use Claroline\CoreBundle\Entity\Planning\PlannedObject;
use Claroline\CoreBundle\Entity\User;
use Claroline\AppBundle\Event\CrudEvents;
use Claroline\CoreBundle\Manager\FileManager;
use Claroline\CoreBundle\Manager\PlanningManager;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
Expand Down Expand Up @@ -55,6 +56,7 @@ public static function getSubscribedEvents(): array
CrudEvents::getEventName(CrudEvents::POST_CREATE, static::getPlannedClass()) => 'postCreate',
CrudEvents::getEventName(CrudEvents::PRE_UPDATE, static::getPlannedClass()) => 'preUpdate',
CrudEvents::getEventName(CrudEvents::POST_DELETE, static::getPlannedClass()) => 'postDelete',
CrudEvents::getEventName(CrudEvents::PRE_COPY, static::getPlannedClass()) => 'preCopy',
];
}

Expand Down Expand Up @@ -151,4 +153,12 @@ public function postDelete(DeleteEvent $event): void
$this->fileManager->unlinkFile(PlannedObject::class, $object->getUuid(), $object->getThumbnail());
}
}

public function preCopy(CopyEvent $event): void
{
/** @var AbstractPlanned $copy */
$copy = $event->getCopy();
$copy->setCreatedAt(new \DateTime());
$copy->setUpdatedAt(new \DateTime());
WolfyWin marked this conversation as resolved.
Show resolved Hide resolved
}
}
29 changes: 29 additions & 0 deletions src/plugin/cursus/Controller/CourseController.php
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,35 @@ public function restoreAction(Request $request): JsonResponse
}, $processed));
}

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

$this->om->startFlushSuite();

$data = json_decode($request->getContent(), true);
WolfyWin marked this conversation as resolved.
Show resolved Hide resolved

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

foreach ($courses as $course) {
if ($this->authorization->isGranted('ADMINISTRATE', $course)) {
$processed[] = $this->crud->copy($course);
}
}

$this->om->endFlushSuite();

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

/**
* @Route("/{slug}/open", name="open", methods={"GET"})
*
Expand Down
29 changes: 29 additions & 0 deletions src/plugin/cursus/Controller/EventController.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,35 @@ protected function getDefaultHiddenFilters(): array
return [];
}

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

$this->om->startFlushSuite();

$data = json_decode($request->getContent(), true);
WolfyWin marked this conversation as resolved.
Show resolved Hide resolved

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

foreach ($events as $event) {
if ($this->authorization->isGranted('EDIT', $event)) {
$processed[] = $this->crud->copy($event, [], ['parent' => $event->getSession()]);
}
}

$this->om->endFlushSuite();

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

/**
* @Route("/{workspace}", name="list", methods={"GET"})
*
Expand Down
29 changes: 29 additions & 0 deletions src/plugin/cursus/Controller/SessionController.php
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,35 @@ public function listPublicAction(Request $request): JsonResponse
);
}

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

$this->om->startFlushSuite();

$data = json_decode($request->getContent(), true);
WolfyWin marked this conversation as resolved.
Show resolved Hide resolved

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

foreach ($sessions as $session) {
if ($this->authorization->isGranted('EDIT', $session)) {
$processed[] = $this->crud->copy($session, [], ['parent' => $session->getCourse()]);
}
}

$this->om->endFlushSuite();

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

/**
* @Route("/{id}/pdf", name="download_pdf", methods={"GET"})
*
Expand Down
3 changes: 3 additions & 0 deletions src/plugin/cursus/Repository/CourseRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

namespace Claroline\CursusBundle\Repository;

use Claroline\AppBundle\Repository\UniqueValueFinder;
use Claroline\CoreBundle\Entity\Facet\FieldFacet;
use Claroline\CoreBundle\Entity\User;
use Claroline\CoreBundle\Entity\Workspace\Workspace;
Expand All @@ -21,6 +22,8 @@

class CourseRepository extends EntityRepository
{
use UniqueValueFinder;

public function search(string $search, int $nbResults)
{
return $this->createQueryBuilder('c')
Expand Down
3 changes: 3 additions & 0 deletions src/plugin/cursus/Repository/EventRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,16 @@

namespace Claroline\CursusBundle\Repository;

use Claroline\AppBundle\Repository\UniqueValueFinder;
use Claroline\CoreBundle\Entity\User;
use Claroline\CursusBundle\Entity\Event;
use Claroline\CursusBundle\Entity\Registration\AbstractRegistration;
use Doctrine\ORM\EntityRepository;

class EventRepository extends EntityRepository
{
use UniqueValueFinder;

public function countParticipants(Event $event): array
{
return [
Expand Down
3 changes: 3 additions & 0 deletions src/plugin/cursus/Repository/SessionRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

namespace Claroline\CursusBundle\Repository;

use Claroline\AppBundle\Repository\UniqueValueFinder;
use Claroline\CoreBundle\Entity\User;
use Claroline\CoreBundle\Entity\Workspace\Workspace;
use Claroline\CursusBundle\Entity\Course;
Expand All @@ -20,6 +21,8 @@

class SessionRepository extends EntityRepository
{
use UniqueValueFinder;

public function findByWorkspace(Workspace $workspace)
{
return $this->getEntityManager()
Expand Down
3 changes: 3 additions & 0 deletions src/plugin/cursus/Resources/config/services/subscriber.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ services:
- '@security.token_storage'
- '@Claroline\AppBundle\Persistence\ObjectManager'
- '@Claroline\CoreBundle\Manager\FileManager'
- '@Claroline\AppBundle\API\Crud'
tags:
- { name: kernel.event_subscriber }

Expand All @@ -33,8 +34,10 @@ services:
Claroline\CursusBundle\Subscriber\Crud\SessionSubscriber:
arguments:
- '@security.token_storage'
- '@Claroline\AppBundle\Persistence\ObjectManager'
- '@Claroline\CoreBundle\Manager\FileManager'
- '@Claroline\CursusBundle\Manager\SessionManager'
- '@Claroline\AppBundle\API\Crud'
tags:
- { name: kernel.event_subscriber }

Expand Down
48 changes: 48 additions & 0 deletions src/plugin/cursus/Resources/modules/actions/course/copy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import {createElement} from 'react'

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'

export default (courses, refresher) => {
const processable = courses.filter(course => hasPermission('administrate', course))

return {
name: 'copy',
type: ASYNC_BUTTON,
icon: 'fa fa-fw fa-clone',
label: trans('copy', {}, 'actions'),
displayed: 0 !== processable.length,
confirm: {
title: transChoice('copy_course_confirm_title', processable.length, {}, 'actions'),
subtitle: 1 === processable.length ? processable[0].name : transChoice('count_elements', processable.length, {count: processable.length}),
message: transChoice('copy_course_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',
size: 'xs',
data: course
})))
]
},
request: {
url: url(['apiv2_cursus_course_copy']),
request: {
method: 'POST',
body: JSON.stringify({
ids: processable.map(course => course.id)
})
},
success: (response) => refresher.update(response)
},
group: trans('management'),
scope: ['object', 'collection']
}
}
31 changes: 27 additions & 4 deletions src/plugin/cursus/Resources/modules/event/components/list.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,17 @@ import {connect} from 'react-redux'
import get from 'lodash/get'
import omit from 'lodash/omit'

import {trans} from '#/main/app/intl/translation'
import {url} from '#/main/app/api'
import {hasPermission} from '#/main/app/security'
import {LINK_BUTTON, MODAL_BUTTON, URL_BUTTON} from '#/main/app/buttons'
import {trans, transChoice} from '#/main/app/intl/translation'
import {ListData} from '#/main/app/content/list/containers/data'
import {actions as listActions} from '#/main/app/content/list/store'
import {constants as listConst} from '#/main/app/content/list/constants'
import {ASYNC_BUTTON, LINK_BUTTON, MODAL_BUTTON, URL_BUTTON} from '#/main/app/buttons'

import {constants} from '#/plugin/cursus/constants'
import {EventStatus} from '#/plugin/cursus/components/event-status'
import {EventCard} from '#/plugin/cursus/event/components/card'
import {EventStatus} from '#/plugin/cursus/components/event-status'
import {constants as listConst} from '#/main/app/content/list/constants'
import {MODAL_TRAINING_EVENT_ABOUT} from '#/plugin/cursus/event/modals/about'
import {MODAL_TRAINING_EVENT_PARAMETERS} from '#/plugin/cursus/event/modals/parameters'

Expand Down Expand Up @@ -46,6 +47,28 @@ const Events = (props) =>
scope: ['object'],
group: trans('management'),
displayed: hasPermission('edit', rows[0])
}, {
name: 'copy',
type: ASYNC_BUTTON,
icon: 'fa fa-fw fa-clone',
label: trans('copy', {}, 'actions'),
displayed: hasPermission('edit', rows[0]),
confirm: {
title: transChoice('copy_event_confirm_title', rows.length, {}, 'actions'),
subtitle: 1 === rows.length ? rows[0].name : transChoice('count_elements', rows.length, {count: rows.length}),
message: transChoice('copy_event_confirm_message', rows.length, {count: rows.length}, 'actions')
},
request: {
url: url(['apiv2_cursus_event_copy']),
request: {
method: 'POST',
body: JSON.stringify({
ids: rows.map(row => row.id)
})
}
},
group: trans('management'),
scope: ['object', 'collection']
}, {
name: 'export-pdf',
type: URL_BUTTON,
Expand Down
3 changes: 2 additions & 1 deletion src/plugin/cursus/Resources/modules/plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ registry.add('ClarolineCursusBundle', {
'export-pdf': () => { return import(/* webpackChunkName: "training-action-course-export-pdf" */ '#/plugin/cursus/actions/course/export-pdf') },
'delete' : () => { return import(/* webpackChunkName: "training-action-course-delete" */ '#/plugin/cursus/actions/course/delete') },
'archive' : () => { return import(/* webpackChunkName: "training-action-course-archive" */ '#/plugin/cursus/actions/course/archive') },
'restore' : () => { return import(/* webpackChunkName: "training-action-course-restore" */ '#/plugin/cursus/actions/course/restore') }
'restore' : () => { return import(/* webpackChunkName: "training-action-course-restore" */ '#/plugin/cursus/actions/course/restore') },
'copy' : () => { return import(/* webpackChunkName: "training-action-course-copy" */ '#/plugin/cursus/actions/course/copy') }
},
training_presence: {
'export-pdf' : () => { return import(/* webpackChunkName: "training-action-presence-export-pdf" */ '#/plugin/cursus/actions/presence/export-pdf') },
Expand Down
Loading
Loading