- New datagrid bundle added (apy/datagrid-bundle) - api_get_group_entity() added - ResourceController and uploader fixed using new version of Resource bundle. - Add interface and trait to capture the course and session from the url with a listener. - Add new form type to manage Resource (Link, Node and Rights) - Fix ResourceRepository with new changes - New templates added for the document list (dummy code)pull/2650/head
parent
3b87f8575e
commit
3f8b6c39f8
@ -0,0 +1,151 @@ |
||||
<?php |
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\CoreBundle\Controller; |
||||
|
||||
use Chamilo\CoreBundle\Repository\ResourceRepository; |
||||
use Chamilo\CoreBundle\Entity\Resource\ResourceLink; |
||||
use Chamilo\CoreBundle\Entity\Resource\ResourceNode; |
||||
use Chamilo\CoreBundle\Entity\Resource\ResourceRights; |
||||
use League\Flysystem\Adapter\Local; |
||||
use League\Flysystem\Filesystem; |
||||
use APY\DataGridBundle\Grid\Action\MassAction; |
||||
use APY\DataGridBundle\Grid\Action\RowAction; |
||||
use Symfony\Component\HttpFoundation\BinaryFileResponse; |
||||
use Symfony\Component\HttpFoundation\File\MimeType\FileinfoMimeTypeGuesser; |
||||
use Symfony\Component\HttpFoundation\Request; |
||||
use Symfony\Component\HttpFoundation\Response; |
||||
use Symfony\Component\HttpFoundation\ResponseHeaderBag; |
||||
use Symfony\Component\Routing\Annotation\Route; |
||||
use APY\DataGridBundle\Grid\Source\Entity; |
||||
use FOS\RestBundle\View\View; |
||||
use Sylius\Component\Resource\ResourceActions; |
||||
use Chamilo\CoreBundle\Security\Authorization\Voter\ResourceNodeVoter; |
||||
|
||||
/** |
||||
* Class ResourceController. |
||||
* |
||||
* @author Julio Montoya <gugli100@gmail.com>. |
||||
* |
||||
* @Route("/resource") |
||||
* |
||||
* @package Chamilo\CoreBundle\Controller |
||||
*/ |
||||
class ResourceDownloadController extends BaseController |
||||
{ |
||||
/** |
||||
* Upload form |
||||
* @Route("/upload/{type}/{id}", name="resource_upload", methods={"GET", "POST"}, options={"expose"=true}) |
||||
* |
||||
* @return Response |
||||
*/ |
||||
public function showUploadFormAction($type, $id): Response |
||||
{ |
||||
//$helper = $this->container->get('oneup_uploader.templating.uploader_helper'); |
||||
//$endpoint = $helper->endpoint('courses'); |
||||
return $this->render( |
||||
'@ChamiloCore/Resource/upload.html.twig', |
||||
[ |
||||
'identifier' => $id, |
||||
'type' => $type, |
||||
] |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* Downloads the file courses/MATHS/document/file.jpg to the user. |
||||
* @Route("/download/{course}/", name="resource_download", methods={"GET"}, options={"expose"=true}) |
||||
* @todo check permissions |
||||
* |
||||
* @param string $course |
||||
* |
||||
* @return \Symfony\Component\HttpKernel\Exception\NotFoundHttpException |
||||
*/ |
||||
public function downloadFileAction(Request $request, $course) |
||||
{ |
||||
try { |
||||
/** @var Filesystem $fs */ |
||||
$fs = $this->container->get('oneup_flysystem.courses_filesystem'); |
||||
$file = $request->get('file'); |
||||
|
||||
$path = $course.'/document/'.$file; |
||||
|
||||
// Has folder |
||||
if (!$fs->has($course)) { |
||||
return $this->abort(); |
||||
} |
||||
|
||||
// Has file |
||||
if (!$fs->has($path)) { |
||||
return $this->abort(); |
||||
} |
||||
|
||||
/** @var Local $adapter */ |
||||
$adapter = $fs->getAdapter(); |
||||
$filePath = $adapter->getPathPrefix().$path; |
||||
|
||||
$response = new BinaryFileResponse($filePath); |
||||
|
||||
// To generate a file download, you need the mimetype of the file |
||||
$mimeTypeGuesser = new FileinfoMimeTypeGuesser(); |
||||
|
||||
// Set the mimetype with the guesser or manually |
||||
if ($mimeTypeGuesser->isSupported()) { |
||||
// Guess the mimetype of the file according to the extension of the file |
||||
$response->headers->set('Content-Type', $mimeTypeGuesser->guess($filePath)); |
||||
} else { |
||||
// Set the mimetype of the file manually, in this case for a text file is text/plain |
||||
$response->headers->set('Content-Type', 'text/plain'); |
||||
} |
||||
|
||||
$response->setContentDisposition( |
||||
ResponseHeaderBag::DISPOSITION_ATTACHMENT, |
||||
basename($filePath) |
||||
); |
||||
|
||||
return $response; |
||||
|
||||
} catch (\InvalidArgumentException $e) { |
||||
return $this->abort(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Gets a document in browser courses/MATHS/document/file.jpg to the user. |
||||
* @Route("/get/{course}/", name="resource_get", methods={"GET"}, options={"expose"=true}) |
||||
* @todo check permissions |
||||
* |
||||
* @param string $course |
||||
* |
||||
* @return \Symfony\Component\HttpKernel\Exception\NotFoundHttpException |
||||
*/ |
||||
public function getFileAction(Request $request, $course) |
||||
{ |
||||
try { |
||||
/** @var Filesystem $fs */ |
||||
$fs = $this->container->get('oneup_flysystem.courses_filesystem'); |
||||
$file = $request->get('file'); |
||||
|
||||
$path = $course.'/document/'.$file; |
||||
|
||||
// Has folder |
||||
if (!$fs->has($course)) { |
||||
return $this->abort(); |
||||
} |
||||
|
||||
// Has file |
||||
if (!$fs->has($path)) { |
||||
return $this->abort(); |
||||
} |
||||
|
||||
/** @var Local $adapter */ |
||||
$adapter = $fs->getAdapter(); |
||||
$filePath = $adapter->getPathPrefix().$path; |
||||
|
||||
return $this->file($filePath, null, ResponseHeaderBag::DISPOSITION_INLINE); |
||||
|
||||
} catch (\InvalidArgumentException $e) { |
||||
return $this->abort(); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,25 @@ |
||||
<?php |
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\CoreBundle\Entity\Resource; |
||||
|
||||
/** |
||||
* Interface ResourceInterface. |
||||
* |
||||
* @package Chamilo\CoreBundle\Entity\Resource |
||||
*/ |
||||
interface ResourceInterface |
||||
{ |
||||
public function setResourceNode(ResourceNode $resourceNode); |
||||
public function getResourceNode(); |
||||
|
||||
/** |
||||
* Returns the resource id. |
||||
* |
||||
* @return int |
||||
*/ |
||||
public function getResourceIdentifier(): int; |
||||
public function getResourceName(): string; |
||||
public function getToolName(): string; |
||||
//"getName()", "name()", "isName()", "hasName()", "__get()" |
||||
} |
||||
@ -0,0 +1,86 @@ |
||||
<?php |
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\CoreBundle\Form\Type; |
||||
|
||||
use Chamilo\CourseBundle\Entity\CDocument; |
||||
use Symfony\Component\Form\AbstractType; |
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType; |
||||
use Symfony\Component\Form\Extension\Core\Type\HiddenType; |
||||
use Symfony\Component\Form\FormBuilderInterface; |
||||
use Symfony\Component\OptionsResolver\OptionsResolver; |
||||
|
||||
/** |
||||
* Class DocumentType |
||||
* @package Chamilo\NotebookBundle\Form\Type |
||||
*/ |
||||
class DocumentType extends AbstractType |
||||
{ |
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function buildForm(FormBuilderInterface $builder, array $options) |
||||
{ |
||||
$builder |
||||
->add('title') |
||||
->add('comment', 'ckeditor') |
||||
->add( |
||||
'shared', |
||||
ChoiceType::class, |
||||
array( |
||||
'choices' => array( |
||||
'This course' => 'this_course', |
||||
'Only me' => 'only_me', |
||||
'Shared' => 'shared', |
||||
), |
||||
'multiple' => false, |
||||
'expanded' => true, |
||||
'required' => true, |
||||
'mapped' => false, |
||||
) |
||||
) |
||||
->add( |
||||
'rights', |
||||
'collection', |
||||
array( |
||||
'entry_type' => ResourceLinkType::class, |
||||
'mapped' => false, |
||||
'allow_add' => true, |
||||
'by_reference' => false, |
||||
'allow_delete' => true, |
||||
) |
||||
) |
||||
->add('c_id', HiddenType::class) |
||||
/*->add( |
||||
'rights', |
||||
'collection', |
||||
array( |
||||
'type' => new ResourceRightsType(), |
||||
'mapped' => false, |
||||
'allow_add' => true, |
||||
) |
||||
)*/ |
||||
//->add('resourceNode', new ResourceNodeType()) |
||||
->add('save', 'submit'); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function configureOptions(OptionsResolver $resolver) |
||||
{ |
||||
$resolver->setDefaults( |
||||
array( |
||||
'data_class' => CDocument::class, |
||||
) |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function getName() |
||||
{ |
||||
return 'chamilo_document'; |
||||
} |
||||
} |
||||
@ -0,0 +1,92 @@ |
||||
<?php |
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\CoreBundle\Form\Type; |
||||
|
||||
use Chamilo\CoreBundle\Entity\ToolResourceRights; |
||||
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType; |
||||
use Symfony\Component\Form\AbstractType; |
||||
use Symfony\Component\Form\FormBuilderInterface; |
||||
use Symfony\Component\OptionsResolver\OptionsResolver; |
||||
|
||||
/** |
||||
* Class ResourceLinkType |
||||
* @package Chamilo\CoreBundle\Form\Type |
||||
*/ |
||||
class ResourceLinkType extends AbstractType |
||||
{ |
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function buildForm(FormBuilderInterface $builder, array $options) |
||||
{ |
||||
$builder |
||||
->add( |
||||
'sharing', |
||||
ChoiceType::class, |
||||
array( |
||||
'choices' => array( |
||||
'everyone' => 'Everyone', |
||||
'course' => 'Course', |
||||
'user' => 'User', |
||||
'group' => 'Group', |
||||
), |
||||
'attr' => array('class' => 'sharing_options'), |
||||
'mapped' => false |
||||
) |
||||
) |
||||
->add( |
||||
'search', |
||||
'hidden', |
||||
array( |
||||
'attr' => array('class' => 'extra_hidden'), |
||||
'mapped' => false |
||||
) |
||||
) |
||||
->add( |
||||
'role', |
||||
ChoiceType::class, |
||||
array( |
||||
'choices' => ToolResourceRights::getDefaultRoles(), |
||||
'mapped' => false |
||||
) |
||||
) |
||||
->add( |
||||
'mask', |
||||
ChoiceType::class, |
||||
array( |
||||
'choices' => ToolResourceRights::getMaskList(), |
||||
'mapped' => false |
||||
) |
||||
)/*->add( |
||||
'rights', |
||||
'collection', |
||||
array( |
||||
'type' => new ResourceRightsType(), |
||||
'allow_add' => true, |
||||
) |
||||
)*/ |
||||
; |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function configureOptions(OptionsResolver $resolver) |
||||
{ |
||||
$resolver->setDefaults( |
||||
array( |
||||
'data_class' => 'Chamilo\CoreBundle\Entity\Resource\ResourceLink', |
||||
) |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function getName() |
||||
{ |
||||
return 'chamilo_resource_link_type'; |
||||
} |
||||
} |
||||
@ -0,0 +1,51 @@ |
||||
<?php |
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\CoreBundle\Form\Type; |
||||
|
||||
use Symfony\Component\Form\AbstractType; |
||||
use Symfony\Component\Form\FormBuilderInterface; |
||||
use Symfony\Component\OptionsResolver\OptionsResolver; |
||||
|
||||
/** |
||||
* Class ResourceNodeType |
||||
* @package Chamilo\NotebookBundle\Form\Type |
||||
*/ |
||||
class ResourceNodeType extends AbstractType |
||||
{ |
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function buildForm(FormBuilderInterface $builder, array $options) |
||||
{ |
||||
$builder |
||||
->add('tool') |
||||
->add( |
||||
'links', |
||||
'collection', |
||||
array( |
||||
'type' => new ResourceLinkType(), |
||||
) |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function configureOptions(OptionsResolver $resolver) |
||||
{ |
||||
$resolver->setDefaults( |
||||
array( |
||||
'data_class' => 'Chamilo\CoreBundle\Entity\Resource\ResourceNode', |
||||
) |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function getName() |
||||
{ |
||||
return 'chamilo_resource_node_type'; |
||||
} |
||||
} |
||||
@ -0,0 +1,54 @@ |
||||
<?php |
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\CoreBundle\Form\Type; |
||||
|
||||
use Chamilo\CoreBundle\Entity\ToolResourceRights; |
||||
use Symfony\Component\Form\AbstractType; |
||||
use Symfony\Component\Form\FormBuilderInterface; |
||||
use Symfony\Component\OptionsResolver\OptionsResolver; |
||||
|
||||
/** |
||||
* Class ResourceRightsType |
||||
* @package Chamilo\NotebookBundle\Form\Type |
||||
*/ |
||||
class ResourceRightsType extends AbstractType |
||||
{ |
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function buildForm(FormBuilderInterface $builder, array $options) |
||||
{ |
||||
$builder |
||||
->add( |
||||
'role', |
||||
'choice', |
||||
array('choices' => ToolResourceRights::getDefaultRoles()) |
||||
) |
||||
->add( |
||||
'mask', |
||||
'choice', |
||||
array('choices' => ToolResourceRights::getMaskList()) |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function configureOptions(OptionsResolver $resolver) |
||||
{ |
||||
$resolver->setDefaults( |
||||
array( |
||||
'data_class' => 'Chamilo\CoreBundle\Entity\Resource\ResourceRights', |
||||
) |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* {@inheritdoc} |
||||
*/ |
||||
public function getName() |
||||
{ |
||||
return 'chamilo_resource_rights_type'; |
||||
} |
||||
} |
||||
@ -0,0 +1,197 @@ |
||||
{% extends "@ChamiloTheme/Layout/layout_one_col.html.twig" %} |
||||
|
||||
{% block content %} |
||||
<script> |
||||
var $collectionHolder; |
||||
|
||||
// setup an "add a tag" link |
||||
var $addTagLink = $('<a href="#" class="btn btn-success add_tag_link">Add</a>'); |
||||
var $newLinkLi = $('<li></li>').append($addTagLink); |
||||
|
||||
jQuery(document).ready(function () { |
||||
// Get the ul that holds the collection of tags |
||||
$collectionHolder = $('ul.tags'); |
||||
|
||||
// add a delete link to all of the existing tag form li elements |
||||
$collectionHolder.find('li').each(function () { |
||||
addTagFormDeleteLink($(this)); |
||||
}); |
||||
|
||||
// add the "add a tag" anchor and li to the tags ul |
||||
$collectionHolder.append($newLinkLi); |
||||
|
||||
// count the current form inputs we have (e.g. 2), use that as the new |
||||
// index when inserting a new item (e.g. 2) |
||||
$collectionHolder.data('index', $collectionHolder.find(':input').length); |
||||
|
||||
$addTagLink.on('click', function (e) { |
||||
// prevent the link from creating a "#" on the URL |
||||
e.preventDefault(); |
||||
|
||||
// add a new tag form (see next code block) |
||||
addTagForm($collectionHolder, $newLinkLi); |
||||
}); |
||||
|
||||
// This course |
||||
$('#chamilo_notebook_notebook_shared_0').on('click', function () { |
||||
$('#rights').hide(); |
||||
}); |
||||
|
||||
// Only me |
||||
$('#chamilo_notebook_notebook_shared_1').on('click', function () { |
||||
$('#rights').hide(); |
||||
}); |
||||
|
||||
// Shared |
||||
$('#chamilo_notebook_notebook_shared_2').on('click', function () { |
||||
$('#rights').show(); |
||||
}); |
||||
}); |
||||
|
||||
function repoFormatResult(repo) { |
||||
console.log(repo); |
||||
var markup = '<div class="row-fluid">' + |
||||
'<div class="span2"><img src="' + repo.owner.avatar_url + '" /></div>' + |
||||
'<div class="span10">' + |
||||
'<div class="row-fluid">' + |
||||
'<div class="span6">' + repo.full_name + '</div>' + |
||||
'<div class="span3"><i class="fa fa-code-fork"></i> ' + repo.forks_count + '</div>' + |
||||
'<div class="span3"><i class="fa fa-star"></i> ' + repo.stargazers_count + '</div>' + |
||||
'</div>'; |
||||
|
||||
if (repo.description) { |
||||
markup += '<div>' + repo.description + '</div>'; |
||||
} |
||||
|
||||
markup += '</div></div>'; |
||||
|
||||
return markup; |
||||
} |
||||
|
||||
function addTagFormDeleteLink($tagFormLi) { |
||||
var $removeFormA = $('<a href="#" class="btn btn-danger">Delete</a>'); |
||||
$tagFormLi.append($removeFormA); |
||||
|
||||
$removeFormA.on('click', function (e) { |
||||
// prevent the link from creating a "#" on the URL |
||||
e.preventDefault(); |
||||
|
||||
// remove the li for the tag form |
||||
$tagFormLi.remove(); |
||||
}); |
||||
} |
||||
|
||||
function addTagForm($collectionHolder, $newLinkLi) { |
||||
// Get the data-prototype explained earlier |
||||
var prototype = $collectionHolder.data('prototype'); |
||||
|
||||
// get the new index |
||||
var index = $collectionHolder.data('index'); |
||||
|
||||
// Replace '__name__' in the prototype's HTML to |
||||
// instead be a number based on how many items we have |
||||
var newForm = prototype.replace(/__name__/g, index); |
||||
|
||||
// increase the index with one for the next item |
||||
$collectionHolder.data('index', index + 1); |
||||
|
||||
// Display the form in the page in an li, before the "Add a tag" link li |
||||
var $newFormLi = $('<li></li>').append(newForm); |
||||
$newLinkLi.before($newFormLi); |
||||
addTagFormDeleteLink($newFormLi); |
||||
|
||||
$('.sharing_options').on('change', function () { |
||||
var inputId = this.id; |
||||
var hiddenInputId = inputId.replace("sharing", "search"); |
||||
var roleId = inputId.replace("sharing", "role"); |
||||
|
||||
var selectRow = $('#' + hiddenInputId); |
||||
var select2 = $('#s2id_' + hiddenInputId); |
||||
var roleRow = $('#' + roleId).parent(); |
||||
|
||||
var url = ''; |
||||
switch (this.value) { |
||||
case 'everyone': |
||||
roleRow.hide(); |
||||
break; |
||||
case 'course': |
||||
selectRow.show(); |
||||
select2.show(); |
||||
roleRow.show(); |
||||
url = Routing.generate('chamilo_core_user_user_mycourses'); |
||||
break; |
||||
case 'user': |
||||
selectRow.show(); |
||||
select2.show(); |
||||
roleRow.hide(); |
||||
url = Routing.generate('chamilo_core_user_user_mycourses'); |
||||
break; |
||||
case 'group': |
||||
selectRow.show(); |
||||
select2.show(); |
||||
roleRow.hide(); |
||||
url = Routing.generate('chamilo_core_user_user_mycourses'); |
||||
break; |
||||
default: |
||||
selectRow.hide(); |
||||
select2.hide(); |
||||
break; |
||||
} |
||||
|
||||
if (url != '') { |
||||
selectRow.select2({ |
||||
tags: true, |
||||
tokenSeparators: [',', ' '], |
||||
ajax: { |
||||
url: url, |
||||
dataType: 'json', |
||||
type: "GET", |
||||
delay: 250, |
||||
data: function (params) { |
||||
return { |
||||
q: params.term, // search term |
||||
page: params.page |
||||
}; |
||||
}, |
||||
results: function (data, page) { |
||||
data = data.items; |
||||
return { |
||||
results: $.map(data, function (item) { |
||||
return { |
||||
text: item.title, |
||||
slug: item.title, |
||||
id: item.id |
||||
} |
||||
}) |
||||
}; |
||||
} |
||||
} |
||||
}); |
||||
} |
||||
}); |
||||
} |
||||
</script> |
||||
|
||||
<div class="box box-primary"> |
||||
<div class="box-header"> |
||||
<h3 class="box-title">Create</h3> |
||||
</div> |
||||
<form method="post" |
||||
action="{{ path('app_document_create', {'c_id': course.id }) }}"> |
||||
<div class="box-body"> |
||||
{{ form_start(form) }} |
||||
{{ form_row(form.title) }} |
||||
{{ form_row(form.comment) }} |
||||
{{ form_row(form.c_id) }} |
||||
{{ form_row(form.shared) }} |
||||
|
||||
<ul id="rights" class="tags" |
||||
data-prototype="{{ form_widget(form.rights.vars.prototype)|e }}"> |
||||
</ul> |
||||
|
||||
{{ form_end(form) }} |
||||
</div> |
||||
</form> |
||||
</div> |
||||
|
||||
{% endblock %} |
||||
@ -0,0 +1,21 @@ |
||||
{% extends 'ChamiloCoreBundle::grid.html.twig' %} |
||||
|
||||
{% block grid_column_id_cell %} |
||||
<a href="{{ url('app_document_show', {'id': row.getField('id'), 'course': course }) }}"> |
||||
{{ row.getField('id') }} |
||||
</a> |
||||
{% endblock %} |
||||
|
||||
{% block grid_column_name_cell %} |
||||
<a href="{{ url('app_document_show', {'id': row.getField('id'), 'course': course }) }}"> |
||||
{{ value }} |
||||
</a> |
||||
{% endblock %} |
||||
|
||||
{#{% block grid_column_actions_cell %}#} |
||||
{#<div class="btn-group">#} |
||||
|
||||
|
||||
{#{{ parent() }}#} |
||||
{#</div>#} |
||||
{#{% endblock grid_column_actions_cell %}#} |
||||
@ -0,0 +1,147 @@ |
||||
{% extends "@ChamiloTheme/Layout/layout_one_col.html.twig" %} |
||||
|
||||
{% block content %} |
||||
<style> |
||||
.grid table |
||||
{ |
||||
font-family: "Trebuchet MS", Arial, Helvetica, sans-serif; |
||||
border-collapse: collapse; |
||||
color: #555555; |
||||
font-size: 1em; |
||||
width: 100%; |
||||
} |
||||
|
||||
.grid td, .grid th |
||||
{ |
||||
border: 1px solid #D4E0EE; |
||||
padding: 3px 7px 2px 7px; |
||||
} |
||||
.grid th |
||||
{ |
||||
background-color: #E6EDF5; |
||||
vertical-align: top; |
||||
} |
||||
|
||||
.grid th a { |
||||
color: #4F76A3; |
||||
text-decoration: none; |
||||
} |
||||
|
||||
.grid th a.grid-reset { |
||||
margin-left: 5px; |
||||
font-weight: normal; |
||||
} |
||||
|
||||
.grid tr.even |
||||
{ |
||||
background-color: #FCFDFE; |
||||
} |
||||
|
||||
.grid tr.odd { |
||||
background-color: #F7F9FC; |
||||
|
||||
} |
||||
|
||||
.grid_header, .grid_footer { |
||||
margin: 5px 0; |
||||
} |
||||
|
||||
/* Icons for order */ |
||||
/* You can find this icons in the images directory of the docuementation */ |
||||
th div { |
||||
height: 10px; |
||||
width: 20px; |
||||
float: right; |
||||
padding-top: 4px; |
||||
} |
||||
|
||||
.grid th div.sort_up { |
||||
background: transparent url("data:image/gif;base64,R0lGODlhFwAKAIABAJCQkO/v7yH+EUNyZWF0ZWQgd2l0aCBHSU1QACH5BAEKAAEALAAAAAAXAAoAAAIajI+py+0GwGsxTmVDvlqe/YCQ52wmyaXqUQAAOw==") no-repeat bottom left; |
||||
} |
||||
|
||||
.grid th div.sort_down { |
||||
background: transparent url("data:image/gif;base64,R0lGODlhFwAKAHAAACH5BAEAAAIALAAAAAAXAAoAgQAAAJCQkAAAAAAAAAIalI+py60RDpTRiZmwvdXozXkdKH6keKZqUwAAOw==") no-repeat bottom left; |
||||
} |
||||
|
||||
/* Boolean column */ |
||||
.grid .grid_boolean_true { |
||||
background: transparent url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACl0lEQVR42q2T60uTYRiH/Tv2bnttAwlkRCGChFD7FCQSm2ZDMQ/L0nRnj7TNGDbTooychzFSSssstdqc8zB1anNrSpm47FVCzH3pQLVhdLBfzztoJlifvOEHz4fnuu7nGBe311XgOyLMnTmsz/akMBljB8OSEVFY4kpkJM5Efbp9v/C/cJ43VSrzJId0HhluBy3oW+mKpnOpGSWuExD30iFxDy3dFSZdpZkTSZHr80Y41/phe3UDpvnKaNixY60PjbNVOGTjRZJtvJ2SHE+KINOdtMHC7MSaQBkq/CXQzJ6DjqScpNp3HvY3D3B5ugIiC3dDdJMriAlk7iSDajwr2pmFWVDlPQPFTCEU0wVQTxfCvT4Ig1cJB5Hk9hxDwjWuISbIGBExncFmWINNqPAVQ/lUTsB8KKdIPPmYeOsCW6HIOtpeNMI234j4ei4TExy3J2w+Wr2L2oAGWm8RWckAlj4uQDVZiPH1oSj8c+sH2p5fgWGyGH3BTvCN1GZMIH5Ib/avdMPoV6HWr8Xnb5+i0Iev72KwZa4ealc29O6z6A92gF/zt6CHZm4tNKF98Sp0U3KYfdWIfP8Shbd+bcHy7BLKnFnQEEFLoA7tXjPoKmp7C6l3+Ab5QBrsq/dRPSmH2n0adTPlWH6/iLa5BpQOnoTCcQo6Zw7sr7uRbj0KupLaPsRkK09wgFyN2aPBY+YeKkfzoB3OgWpIBqWDDQtn48lyF4xDxeCrORu0mhLseAuJTVxpfAMVMbnL4CCS1oAZ+tEiXBiWo5VswU5gvbMIvFJOhMC7v8Z9DVwpbaJCkg4x2v1m9L60onfBCovXhLSWVPAVnBCt+gf8p+iLXCFtoPR0DcXwtZwwX8UJk44MiZ4upYR7/nt/A+w9sdKFchsrAAAAAElFTkSuQmCC") no-repeat bottom left; |
||||
display: inline-block; |
||||
text-indent: 16px; |
||||
width: 16px; |
||||
overflow: hidden; |
||||
} |
||||
|
||||
.grid .grid_boolean_false { |
||||
background: transparent url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACSElEQVR42q2Ty0vUURTHv/5SJ1SmUaGckUYdG5FyVdAicGMkFAXBtEl8gJseIP0FEVEtbNNiFm0iMMUgGKhVIUj0oqKFQ40N2TwwdewxOik6zcy953tbmD/HxFV9d/dwz+f7PXAO8I8q+bugb1xspjFdhuwlWUcSJL+SvEfhaPXgcHxbQOH6hYChCa6WlLvLm/eh1OkEAKjlJWSjUVjZpXlSBvbcehDaAshfOx8w5FB+t7eyosUPSU2DqWkAgOX2wvI0YPljFLmpD6sU6fPefhSyAbmr53wkXxTqvJ7KlhYUXo0BACou3wEArFzpB2hQ3t6JpcgkVqITKSHb/XefJCwAENHdWcux0WwMDI09GjUh2iA7/hjO1v0wVbUerVQ3AFgAoLXucfj9kNkkDA0oBkZzE4BKIAUin4hjV2sblFI9xYD6MpcLeiYJo2k7rksKhKi1ei4WR5mrBlrp+g2A0jBi7MZ1RzUV2RhB/YEIASG0VihKoOby6UVY7gY7qiji18txrDy8b7tTEaV7G5FNp6GVnitOMPwz8h47PI32Z1GEs/8Sqk6fBRUhmhAhHI0+fA+/g9Z62AYopUYKC6lUZjKCio7jNmQxeBMLwUGIrL1dJ07iRySMzMznlNZ6ZNMiTXZ3BCgy5DpwuLK6tQ25ZAK5WBzGGDiafHA0+ZCOhPHl9dgqyb6jTz+FtqzyxJkjASGDO2s87tq2g3C4qmEMkMss4tvEW2RmY/MkB449mwpte0xvTh1qJtlFYS8pm4+JHO18Hovjf+o3Xg+XX4ZLBPIAAAAASUVORK5CYII=") no-repeat bottom left; |
||||
display: inline-block; |
||||
text-indent: 16px; |
||||
width: 16px; |
||||
overflow: hidden; |
||||
} |
||||
|
||||
/* Alignement */ |
||||
.grid .align-left { |
||||
text-align: left; |
||||
} |
||||
|
||||
.grid .align-center { |
||||
text-align: center; |
||||
} |
||||
|
||||
.grid .align-right { |
||||
text-align: right; |
||||
} |
||||
|
||||
/* Column filter */ |
||||
.grid .grid-filter-operator select{ |
||||
width: 70px; |
||||
|
||||
} |
||||
|
||||
.grid .grid-filter-input-query input, .grid .grid-filter-select-query select{ |
||||
width: 50px; |
||||
} |
||||
|
||||
.grid .grid-filter-input-query-to, .grid .grid-filter-select-query-to{ |
||||
margin-left: 77px; |
||||
display: block; |
||||
} |
||||
|
||||
/* Grid Search */ |
||||
|
||||
.grid-search { |
||||
border: 1px solid #D4E0EE; |
||||
padding: 10px; |
||||
} |
||||
|
||||
.grid-search label{ |
||||
width: 80px; |
||||
display: inline-block; |
||||
text-align: right; |
||||
} |
||||
|
||||
.grid-search select, .grid-search .grid-filter-input-query input { |
||||
width: 150px; |
||||
} |
||||
</style> |
||||
{% if is_granted('ROLE_CURRENT_COURSE_TEACHER') %} |
||||
<div class="actions"> |
||||
<a class="btn btn-default" |
||||
href="{{ url('app_document_create', { 'c_id': course.id }) }}"> |
||||
{{ 'Add' | trans }} |
||||
</a> |
||||
</div> |
||||
{% endif %} |
||||
|
||||
<div class="row"> |
||||
{{ grid(grid, 'ChamiloCoreBundle:Document:grid.html.twig') }} |
||||
{{ grid_search(grid) }} |
||||
</div> |
||||
|
||||
{# ajax #} |
||||
{#{{ grid_search(grid, 'APYDataGridBundle::blocks.html.twig') }}#} |
||||
|
||||
{#{{ grid(grid, 'APYDataGridBundle::blocks_js.jquery.html.twig') }}#} |
||||
|
||||
{% endblock %} |
||||
@ -0,0 +1,47 @@ |
||||
{% extends "@ChamiloTheme/Layout/layout_one_col.html.twig" %} |
||||
|
||||
{% block content %} |
||||
<h2>{{ resource.title }}</h2> |
||||
{{ resource.comment| raw }} |
||||
|
||||
<div class="box box-solid"> |
||||
<div class="box-header"> |
||||
<i class="fa fa-info-circle"></i> |
||||
<h3 class="box-title">{{ 'Description' | trans }}</h3> |
||||
</div><!-- /.box-header --> |
||||
|
||||
<div class="box-body"> |
||||
<dl class="dl-horizontal"> |
||||
<dt>{{ 'Creator' | trans }}</dt> |
||||
<dd>{{ resource.resourceNode.creator.username }}</dd> |
||||
<dt>{{ 'CreatedAt' | trans }}</dt> |
||||
<dd>{{ resource.resourceNode.createdAt | format_datetime }}</dd> |
||||
<dt>{{ 'UpdatedAt' | trans }}</dt> |
||||
<dd>{{ resource.resourceNode.updatedAt | format_datetime }}</dd> |
||||
<dt>{{ 'Shared' | trans }}</dt> |
||||
|
||||
{% for link in resource.resourceNode.links %} |
||||
{% if link.private %} |
||||
<dd>Only with me</dd> |
||||
{% else %} |
||||
{% if link.course %} |
||||
<dd> {{ 'Course' | trans }} : {{ link.course.title }} |
||||
({{ link.course.code }}) |
||||
</dd> |
||||
{% endif %} |
||||
{% if link.session %} |
||||
<dd> {{ 'Session' | trans }} : {{ link.session.title }} |
||||
({{ link.session.title }}) |
||||
</dd> |
||||
{% endif %} |
||||
{% endif %} |
||||
|
||||
{% for right in link.rights %} |
||||
{{ right.role }} - {{ right.mask }} |
||||
{% endfor %} |
||||
{% endfor %} |
||||
</dl> |
||||
</div><!-- /.box-body --> |
||||
</div> |
||||
|
||||
{% endblock %} |
||||
@ -0,0 +1,10 @@ |
||||
{% extends "@ChamiloTheme/Layout/layout_one_col.html.twig" %} |
||||
|
||||
{% block content %} |
||||
<form method="post" |
||||
action="{{ path('app_document_update', {'c_id': course.id, 'id' : resource.iid } ) }}"> |
||||
<input type="hidden" name="_method" value="PUT"/> |
||||
{{ form_widget(form) }} |
||||
</form> |
||||
|
||||
{% endblock %} |
||||
@ -0,0 +1,139 @@ |
||||
{% extends 'APYDataGridBundle::blocks.html.twig' %} |
||||
|
||||
{% block grid_actions %} |
||||
<div class="mass-actions"> |
||||
<div class="btn-group" role="group"> |
||||
<span class="grid_massactions_helper"> |
||||
<a class="btn btn-default" href="#" |
||||
onclick="return {{ grid.hash }}_markVisible(true);">{{ 'Select visible'|trans }}</a> |
||||
<a class="btn btn-default" href="#" |
||||
onclick="return {{ grid.hash }}_markVisible(false);">{{ 'Deselect visible'|trans }}</a> |
||||
<a class="btn btn-default" href="#" |
||||
onclick="return {{ grid.hash }}_markAll(true);">{{ 'Select all'|trans }}</a> |
||||
<a class="btn btn-default" href="#" |
||||
onclick="return {{ grid.hash }}_markAll(false);">{{ 'Deselect all'|trans }}</a> |
||||
<span class="mass-actions-selected" |
||||
id="{{ grid.hash }}_mass_action_selected"></span> |
||||
</span> |
||||
</div> |
||||
{% spaceless %} |
||||
<div style="float:right;" class="grid_massactions"> |
||||
{{ 'Action'|trans }} |
||||
<input type="hidden" id="{{ grid.hash }}_mass_action_all" |
||||
name="{{ grid.hash }}[{{ constant('APY\\DataGridBundle\\Grid\\Grid::REQUEST_QUERY_MASS_ACTION_ALL_KEYS_SELECTED') }}]" |
||||
value="0"/> |
||||
<select name="{{ grid.hash }}[{{ constant('APY\\DataGridBundle\\Grid\\Grid::REQUEST_QUERY_MASS_ACTION') }}]"> |
||||
<option value="-1"></option> |
||||
{% for key, massAction in grid.massActions %} |
||||
<option value="{{ key }}">{{ massAction.title|trans }}</option> |
||||
{% endfor %} |
||||
</select> |
||||
<input type="submit" value="{{ 'Submit Action'|trans }}"/> |
||||
</div> |
||||
{% endspaceless %} |
||||
</div> |
||||
{% endblock grid_actions %} |
||||
|
||||
{# Bootstrap changes #} |
||||
{% block grid_column_actions_cell %} |
||||
{% set actions = column.getActionsToRender(row) %} |
||||
<div class="btn-group"> |
||||
{% for action in actions %} |
||||
{% if action.attributes.form_delete is defined and action.attributes.form_delete %} |
||||
<div class="btn-group"> |
||||
<form method="post" action="{{ url(action.route, column.routeParameters(row, action), false) }}"> |
||||
<input type="hidden" name="_method" value="DELETE" /> |
||||
<button type="submit" class="btn btn-danger"> |
||||
{{ action.title|trans }} |
||||
</button> |
||||
</form> |
||||
</div> |
||||
{% else %} |
||||
<a class="btn btn-default" |
||||
href="{{ url(action.route, column.routeParameters(row, action), false) }}" target="{{ action.target }}"{% if action.confirm %} onclick="return confirm('{{ action.confirmMessage }}')"{% endif %}{% for name, value in action.attributes %} {{ name }}="{{ value }}" {% endfor %}> |
||||
{{ action.title|trans }} |
||||
</a> |
||||
{% endif %} |
||||
{% endfor %} |
||||
</div> |
||||
{% endblock grid_column_actions_cell %} |
||||
|
||||
{% block grid %} |
||||
<div class="col-md-10"> |
||||
<div class="box box-primary"> |
||||
<div class="box-body table-responsive no-padding"> |
||||
{% if grid.totalCount > 0 or grid.isFiltered or grid.noDataMessage is same as(false) %} |
||||
<form id="{{ grid.hash }}" action="{{ grid.routeUrl }}" |
||||
method="post"> |
||||
<div class="grid_header"> |
||||
{% if grid.massActions|length > 0 %} |
||||
{{ grid_actions(grid) }} |
||||
{% endif %} |
||||
</div> |
||||
<div class="grid_body"> |
||||
<table class="table table-bordered table-striped"> |
||||
{% if grid.isTitleSectionVisible %} |
||||
{{ grid_titles(grid) }} |
||||
{% endif %} |
||||
{% if grid.isFilterSectionVisible %} |
||||
{{ grid_filters(grid) }} |
||||
{% endif %} |
||||
{{ grid_rows(grid) }} |
||||
</table> |
||||
</div> |
||||
<div class="grid_footer"> |
||||
{% if grid.isPagerSectionVisible %} |
||||
{{ grid_pager(grid) }} |
||||
{% endif %} |
||||
{% if grid.exports|length > 0 %} |
||||
{{ grid_exports(grid) }} |
||||
{% endif %} |
||||
{% if grid.tweaks|length > 0 %} |
||||
{{ grid_tweaks(grid) }} |
||||
{% endif %} |
||||
</div> |
||||
{% if withjs %} |
||||
{{ grid_scripts(grid) }} |
||||
{% endif %} |
||||
</form> |
||||
{% else %} |
||||
{{ grid_no_data(grid) }} |
||||
{% endif %} |
||||
</div> |
||||
</div> |
||||
</div> |
||||
{% endblock grid %} |
||||
|
||||
{% block grid_search %} |
||||
{% if grid.isFilterSectionVisible %} |
||||
<div class="col-md-2"> |
||||
<div class="box box-primary"> |
||||
<div class="box-header"> |
||||
<h4 class="box-title filter_legend inactive">Filters</h4> |
||||
</div> |
||||
|
||||
<div class="box-body"> |
||||
<form id="{{ grid.hash }}_search" |
||||
action="{{ grid.routeUrl }}" method="post"> |
||||
{% for column in grid.columns %} |
||||
{% if column.isFilterable and column.type not in ['actions', 'massaction'] %} |
||||
{% set columnTitle = grid.prefixTitle ~ column.title %} |
||||
<div class="{{ cycle(['odd', 'even'], loop.index) }}"> |
||||
<label>{{ columnTitle|trans }}</label>{{ grid_filter(column, grid, false)|raw }} |
||||
</div> |
||||
{% endif %} |
||||
{% endfor %} |
||||
<div class="grid-search-action"><input type="submit" |
||||
class="grid-search-submit" |
||||
value="{{ 'Search'|trans }}"/><input |
||||
type="button" class="grid-search-reset" |
||||
value="{{ 'Reset'|trans }}" |
||||
onclick="return {{ grid.hash }}_reset();"/> |
||||
</div> |
||||
</form> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
{% endif %} |
||||
{% endblock grid_search %} |
||||
@ -0,0 +1,55 @@ |
||||
<?php |
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\CourseBundle\Controller; |
||||
|
||||
use Chamilo\CoreBundle\Entity\Course; |
||||
use Chamilo\CoreBundle\Entity\Session; |
||||
|
||||
/** |
||||
* Trait CourseControllerTrait. |
||||
* Implements the functions defined by the CourseControllerInterface |
||||
* |
||||
* @package Chamilo\CourseBundle\Controller |
||||
*/ |
||||
trait CourseControllerTrait |
||||
{ |
||||
protected $course; |
||||
protected $session; |
||||
|
||||
/** |
||||
* @param Course $course |
||||
* |
||||
* @return mixed |
||||
*/ |
||||
public function setCourse(Course $course) |
||||
{ |
||||
$this->course = $course; |
||||
} |
||||
|
||||
/** |
||||
* @param Session $session |
||||
* |
||||
* @return mixed |
||||
*/ |
||||
public function setSession(Session $session) |
||||
{ |
||||
$this->session = $session; |
||||
} |
||||
|
||||
/** |
||||
* @return Course |
||||
*/ |
||||
public function getCourse() |
||||
{ |
||||
return $this->course; |
||||
} |
||||
|
||||
/** |
||||
* @return Session |
||||
*/ |
||||
public function getSession() |
||||
{ |
||||
return $this->session; |
||||
} |
||||
} |
||||
@ -0,0 +1,19 @@ |
||||
<?php |
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\CourseBundle\Repository; |
||||
|
||||
use Chamilo\CoreBundle\Entity\Course; |
||||
use Chamilo\CoreBundle\Repository\ResourceRepository; |
||||
use Chamilo\CoreBundle\Entity\Session; |
||||
use Chamilo\UserBundle\Entity\User; |
||||
|
||||
/** |
||||
* Class CDocumentRepository. |
||||
* |
||||
* @package Chamilo\CourseBundle\Repository |
||||
*/ |
||||
class CDocumentRepository extends ResourceRepository |
||||
{ |
||||
|
||||
} |
||||
Loading…
Reference in new issue