parent
2a68cd6a43
commit
e0f24d5723
@ -0,0 +1,43 @@ |
||||
<template> |
||||
<v-container fluid> |
||||
<v-row> |
||||
<v-col cols="12" sm="6" md="6"> |
||||
<v-text-field |
||||
v-model="item.title" |
||||
:label="$t('title')" |
||||
type="text" |
||||
/> |
||||
</v-col> |
||||
|
||||
<v-row cols="12"></v-row> |
||||
</v-row> |
||||
|
||||
</v-container> |
||||
</template> |
||||
|
||||
<script> |
||||
|
||||
export default { |
||||
name: 'DocumentsFilter', |
||||
props: { |
||||
values: { |
||||
type: Object, |
||||
required: true |
||||
} |
||||
}, |
||||
data() { |
||||
return {}; |
||||
}, |
||||
mounted() { |
||||
}, |
||||
|
||||
computed: { |
||||
// eslint-disable-next-line |
||||
item() { |
||||
return this.initialValues || this.values; |
||||
} |
||||
}, |
||||
methods: { |
||||
} |
||||
}; |
||||
</script> |
@ -0,0 +1,9 @@ |
||||
<template> |
||||
<router-view></router-view> |
||||
</template> |
||||
|
||||
<script> |
||||
export default { |
||||
name: 'DocumentsLayout' |
||||
} |
||||
</script> |
@ -0,0 +1,33 @@ |
||||
export default { |
||||
path: '/resources/documents', |
||||
name: 'documents', |
||||
component: () => import('../components/documents/Layout'), |
||||
redirect: { name: 'DocumentsList' }, |
||||
children: [ |
||||
{ |
||||
name: 'DocumentsList', |
||||
path: '', |
||||
component: () => import('../views/documents/List') |
||||
}, |
||||
{ |
||||
name: 'DocumentsCreate', |
||||
path: 'new', |
||||
component: () => import('../views/documents/Create') |
||||
}, |
||||
{ |
||||
name: 'DocumentsCreateFile', |
||||
path: 'new', |
||||
component: () => import('../views/documents/CreateFile') |
||||
}, |
||||
{ |
||||
name: 'DocumentsUpdate', |
||||
path: ':id/edit', |
||||
component: () => import('../views/documents/Update') |
||||
}, |
||||
{ |
||||
name: 'DocumentsShow', |
||||
path: ':id', |
||||
component: () => import('../views/documents/Show') |
||||
} |
||||
] |
||||
}; |
@ -0,0 +1,3 @@ |
||||
import makeService from './api'; |
||||
|
||||
export default makeService('documents'); |
@ -0,0 +1,45 @@ |
||||
<template> |
||||
<div> |
||||
<Toolbar :handle-submit="onSendForm" :handle-reset="resetForm"></Toolbar> |
||||
<DocumentsForm ref="createForm" :values="item" :errors="violations" /> |
||||
<Loading :visible="isLoading" /> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import { mapActions } from 'vuex'; |
||||
import { createHelpers } from 'vuex-map-fields'; |
||||
import DocumentsForm from '../../components/documents/Form'; |
||||
import Loading from '../../components/Loading'; |
||||
import Toolbar from '../../components/Toolbar'; |
||||
import CreateMixin from '../../mixins/CreateMixin'; |
||||
|
||||
const servicePrefix = 'Documents'; |
||||
|
||||
const { mapFields } = createHelpers({ |
||||
getterType: 'documents/getField', |
||||
mutationType: 'documents/updateField' |
||||
}); |
||||
|
||||
export default { |
||||
name: 'DocumentsCreate', |
||||
servicePrefix, |
||||
mixins: [CreateMixin], |
||||
components: { |
||||
Loading, |
||||
Toolbar, |
||||
DocumentsForm |
||||
}, |
||||
data() { |
||||
return { |
||||
item: {} |
||||
}; |
||||
}, |
||||
computed: { |
||||
...mapFields(['error', 'isLoading', 'created', 'violations']) |
||||
}, |
||||
methods: { |
||||
...mapActions('documents', ['create', 'reset']) |
||||
} |
||||
}; |
||||
</script> |
@ -0,0 +1,45 @@ |
||||
<template> |
||||
<div> |
||||
<Toolbar :handle-submit="onSendForm" :handle-reset="resetForm"></Toolbar> |
||||
<DocumentsForm ref="createForm" :values="item" :errors="violations" /> |
||||
<Loading :visible="isLoading" /> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import { mapActions } from 'vuex'; |
||||
import { createHelpers } from 'vuex-map-fields'; |
||||
import DocumentsForm from '../../components/documents/Form'; |
||||
import Loading from '../../components/Loading'; |
||||
import Toolbar from '../../components/Toolbar'; |
||||
import CreateMixin from '../../mixins/CreateMixin'; |
||||
|
||||
const servicePrefix = 'Documents'; |
||||
|
||||
const { mapFields } = createHelpers({ |
||||
getterType: 'documents/getField', |
||||
mutationType: 'documents/updateField' |
||||
}); |
||||
|
||||
export default { |
||||
name: 'DocumentsCreate', |
||||
servicePrefix, |
||||
mixins: [CreateMixin], |
||||
components: { |
||||
Loading, |
||||
Toolbar, |
||||
DocumentsForm |
||||
}, |
||||
data() { |
||||
return { |
||||
item: {} |
||||
}; |
||||
}, |
||||
computed: { |
||||
...mapFields(['error', 'isLoading', 'created', 'violations']) |
||||
}, |
||||
methods: { |
||||
...mapActions('documents', ['create', 'reset']) |
||||
} |
||||
}; |
||||
</script> |
@ -0,0 +1,105 @@ |
||||
<template> |
||||
<div class="documents-list"> |
||||
<Toolbar |
||||
:handle-add="addHandler" |
||||
:handle-add-document="addDocumentHandler" |
||||
/> |
||||
|
||||
<v-container grid-list-xl fluid> |
||||
<v-layout row wrap> |
||||
<v-flex lg12> |
||||
<DataFilter :handle-filter="onSendFilter" :handle-reset="resetFilter"> |
||||
<DocumentsFilterForm |
||||
ref="filterForm" |
||||
:values="filters" |
||||
slot="filter" |
||||
/> |
||||
</DataFilter> |
||||
<br /> |
||||
|
||||
<v-data-table |
||||
v-model="selected" |
||||
:headers="headers" |
||||
:items="items" |
||||
:items-per-page.sync="options.itemsPerPage" |
||||
:loading="isLoading" |
||||
:loading-text="$t('Loading...')" |
||||
:options.sync="options" |
||||
:server-items-length="totalItems" |
||||
class="elevation-1" |
||||
item-key="@id" |
||||
show-select |
||||
@update:options="onUpdateOptions" |
||||
> |
||||
<template slot="item.resourceNode" slot-scope="{ item }"> |
||||
{{ item['@id'] }} |
||||
</template> |
||||
|
||||
<ActionCell |
||||
slot="item.action" |
||||
slot-scope="props" |
||||
:handle-show="() => showHandler(props.item)" |
||||
:handle-edit="() => editHandler(props.item)" |
||||
:handle-delete="() => deleteHandler(props.item)" |
||||
></ActionCell> |
||||
</v-data-table> |
||||
</v-flex> |
||||
</v-layout> |
||||
</v-container> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import { mapActions, mapGetters } from 'vuex'; |
||||
import { mapFields } from 'vuex-map-fields'; |
||||
import ListMixin from '../../mixins/ListMixin'; |
||||
import ActionCell from '../../components/ActionCell'; |
||||
import DocumentsFilterForm from '../../components/documents/Filter'; |
||||
import DataFilter from '../../components/DataFilter'; |
||||
import Toolbar from '../../components/Toolbar'; |
||||
|
||||
export default { |
||||
name: 'DocumentsList', |
||||
servicePrefix: 'Documents', |
||||
mixins: [ListMixin], |
||||
components: { |
||||
Toolbar, |
||||
ActionCell, |
||||
DocumentsFilterForm, |
||||
DataFilter |
||||
}, |
||||
data() { |
||||
return { |
||||
headers: [ |
||||
{text: 'Title', value: 'resourceNode.title', sortable: true}, |
||||
{text: 'Last modified', value: 'resourceNode.updatedAt', sortable: true}, |
||||
{ |
||||
text: 'Actions', |
||||
value: 'action', |
||||
sortable: false |
||||
} |
||||
], |
||||
selected: [] |
||||
}; |
||||
}, |
||||
computed: { |
||||
...mapGetters('documents', { |
||||
items: 'list' |
||||
}), |
||||
...mapFields('documents', { |
||||
deletedItem: 'deleted', |
||||
error: 'error', |
||||
isLoading: 'isLoading', |
||||
resetList: 'resetList', |
||||
totalItems: 'totalItems', |
||||
view: 'view' |
||||
}) |
||||
}, |
||||
methods: { |
||||
...mapActions('documents', { |
||||
getPage: 'fetchAll', |
||||
deleteItem: 'del' |
||||
}) |
||||
} |
||||
}; |
||||
</script> |
@ -0,0 +1,98 @@ |
||||
<template> |
||||
<div> |
||||
<Toolbar :handle-edit="editHandler" :handle-delete="del"> |
||||
<template slot="left"> |
||||
<v-toolbar-title v-if="item">{{ |
||||
`${$options.servicePrefix} ${item['@id']}` |
||||
}}</v-toolbar-title> |
||||
</template> |
||||
</Toolbar> |
||||
|
||||
<br /> |
||||
|
||||
<div v-if="item" class="table-documents-show"> |
||||
<v-simple-table> |
||||
<template slot="default"> |
||||
<thead> |
||||
<tr> |
||||
<th>Field</th> |
||||
<th>Value</th> |
||||
<th>Field</th> |
||||
<th>Value</th> |
||||
</tr> |
||||
</thead> |
||||
<tbody> |
||||
<tr> |
||||
<td><strong>{{ $t('title') }}</strong></td> |
||||
<td> |
||||
{{ item['title'] }} |
||||
</td> |
||||
|
||||
<td><strong>{{ $t('comment') }}</strong></td> |
||||
<td> |
||||
{{ item['comment'] }} |
||||
</td> |
||||
|
||||
</tr> |
||||
|
||||
<tr> |
||||
<td><strong>{{ $t('resourceNode') }}</strong></td> |
||||
<td> |
||||
{{ item['resourceNode'] && item['resourceNode'].name }} |
||||
</td> |
||||
<td></td> |
||||
</tr> |
||||
|
||||
<tr> |
||||
<td><strong>{{ $t('file') }}</strong></td> |
||||
<td> |
||||
<div v-if="item['resourceNode']['resourceFile']"> |
||||
<img v-bind:src=" item['resourceNode']['resourceFile']['file'] " /> |
||||
</div> |
||||
<div v-else> |
||||
- |
||||
</div> |
||||
</td> |
||||
<td></td> |
||||
</tr> |
||||
</tbody> |
||||
</template> |
||||
</v-simple-table> |
||||
</div> |
||||
|
||||
<Loading :visible="isLoading" /> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import { mapActions, mapGetters } from 'vuex'; |
||||
import { mapFields } from 'vuex-map-fields'; |
||||
import Loading from '../../components/Loading'; |
||||
import ShowMixin from '../../mixins/ShowMixin'; |
||||
import Toolbar from '../../components/Toolbar'; |
||||
|
||||
const servicePrefix = 'Documents'; |
||||
|
||||
export default { |
||||
name: 'DocumentsShow', |
||||
servicePrefix, |
||||
components: { |
||||
Loading, |
||||
Toolbar |
||||
}, |
||||
mixins: [ShowMixin], |
||||
computed: { |
||||
...mapFields('documents', { |
||||
isLoading: 'isLoading' |
||||
}), |
||||
...mapGetters('documents', ['find']) |
||||
}, |
||||
methods: { |
||||
...mapActions('documents', { |
||||
deleteItem: 'del', |
||||
reset: 'resetShow', |
||||
retrieve: 'load' |
||||
}) |
||||
} |
||||
}; |
||||
</script> |
@ -0,0 +1,61 @@ |
||||
<template> |
||||
<div> |
||||
<Toolbar |
||||
:handle-submit="onSendForm" |
||||
:handle-reset="resetForm" |
||||
:handle-delete="del" |
||||
/> |
||||
<DocumentsForm |
||||
ref="updateForm" |
||||
v-if="item" |
||||
:values="item" |
||||
:errors="violations" |
||||
/> |
||||
<Loading :visible="isLoading || deleteLoading" /> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import { mapActions, mapGetters } from 'vuex'; |
||||
import { mapFields } from 'vuex-map-fields'; |
||||
import DocumentsForm from '../../components/documents/Form.vue'; |
||||
import Loading from '../../components/Loading'; |
||||
import Toolbar from '../../components/Toolbar'; |
||||
import UpdateMixin from '../../mixins/UpdateMixin'; |
||||
|
||||
const servicePrefix = 'Documents'; |
||||
|
||||
export default { |
||||
name: 'DocumentsUpdate', |
||||
servicePrefix, |
||||
mixins: [UpdateMixin], |
||||
components: { |
||||
Loading, |
||||
Toolbar, |
||||
DocumentsForm |
||||
}, |
||||
|
||||
computed: { |
||||
...mapFields('documents', { |
||||
deleteLoading: 'isLoading', |
||||
isLoading: 'isLoading', |
||||
error: 'error', |
||||
updated: 'updated', |
||||
violations: 'violations' |
||||
}), |
||||
...mapGetters('documents', ['find']) |
||||
|
||||
}, |
||||
|
||||
methods: { |
||||
...mapActions('documents', { |
||||
createReset: 'resetCreate', |
||||
deleteItem: 'del', |
||||
delReset: 'resetDelete', |
||||
retrieve: 'load', |
||||
update: 'update', |
||||
updateReset: 'resetUpdate' |
||||
}) |
||||
} |
||||
}; |
||||
</script> |
@ -0,0 +1,25 @@ |
||||
<?php |
||||
|
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\CoreBundle\Controller; |
||||
|
||||
use Chamilo\CoreBundle\Entity\Resource\ResourceFile; |
||||
use Symfony\Component\HttpFoundation\Request; |
||||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; |
||||
|
||||
class CreateMediaObjectAction |
||||
{ |
||||
public function __invoke(Request $request): ResourceFile |
||||
{ |
||||
$uploadedFile = $request->files->get('file'); |
||||
if (!$uploadedFile) { |
||||
throw new BadRequestHttpException('"file" is required'); |
||||
} |
||||
|
||||
$resourceFile = new ResourceFile(); |
||||
$resourceFile->setFile($uploadedFile); |
||||
|
||||
return $resourceFile; |
||||
} |
||||
} |
@ -0,0 +1,72 @@ |
||||
<?php |
||||
|
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\CoreBundle\EventSubscriber; |
||||
|
||||
use ApiPlatform\Core\EventListener\EventPriorities; |
||||
use ApiPlatform\Core\Util\RequestAttributesExtractor; |
||||
use Chamilo\CoreBundle\Entity\Resource\ResourceFile; |
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface; |
||||
use Symfony\Component\HttpFoundation\Response; |
||||
use Symfony\Component\HttpKernel\Event\ViewEvent; |
||||
use Symfony\Component\HttpKernel\KernelEvents; |
||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface; |
||||
use Symfony\Component\Routing\RouterInterface; |
||||
use Vich\UploaderBundle\Storage\StorageInterface; |
||||
|
||||
class ResolveResourceFileContentUrlSubscriber implements EventSubscriberInterface |
||||
{ |
||||
private $storage; |
||||
private $generator; |
||||
|
||||
public function __construct(StorageInterface $storage, UrlGeneratorInterface $generator) |
||||
{ |
||||
$this->storage = $storage; |
||||
$this->generator = $generator; |
||||
} |
||||
|
||||
public static function getSubscribedEvents(): array |
||||
{ |
||||
return [ |
||||
KernelEvents::VIEW => ['onPreSerialize', EventPriorities::PRE_SERIALIZE], |
||||
]; |
||||
} |
||||
|
||||
public function onPreSerialize(ViewEvent $event): void |
||||
{ |
||||
$controllerResult = $event->getControllerResult(); |
||||
$request = $event->getRequest(); |
||||
|
||||
if ($controllerResult instanceof Response || !$request->attributes->getBoolean('_api_respond', true)) { |
||||
return; |
||||
} |
||||
|
||||
if (!($attributes = RequestAttributesExtractor::extractAttributes($request)) || |
||||
!\is_a($attributes['resource_class'], ResourceFile::class, true) |
||||
) { |
||||
return; |
||||
} |
||||
|
||||
$mediaObjects = $controllerResult; |
||||
|
||||
if (!is_iterable($mediaObjects)) { |
||||
$mediaObjects = [$mediaObjects]; |
||||
} |
||||
|
||||
foreach ($mediaObjects as $mediaObject) { |
||||
if (!$mediaObject instanceof ResourceFile) { |
||||
continue; |
||||
} |
||||
$params = [ |
||||
'id' => $mediaObject->getResourceNode()->getId(), |
||||
'tool' => $mediaObject->getResourceNode()->getResourceType()->getTool()->getName(), |
||||
'type' => $mediaObject->getResourceNode()->getResourceType()->getName(), |
||||
]; |
||||
|
||||
$mediaObject->contentUrl = $this->generator->generate('chamilo_core_resource_view_file', $params); |
||||
|
||||
//$mediaObject->contentUrl = $this->storage->resolveUri($mediaObject, 'file'); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,33 @@ |
||||
{% extends "@ChamiloCore/Layout/no_layout.html.twig" %} |
||||
|
||||
{% block content %} |
||||
<div id="app"> |
||||
</div> |
||||
|
||||
<script> |
||||
/*window.quasarConfig = { |
||||
brand: { // this will NOT work on IE 11 |
||||
primary: '#e46262', |
||||
// ... or all other brand colors |
||||
}, |
||||
notify: { |
||||
position: 'top', |
||||
multiLine: true, |
||||
timeout: 0, |
||||
}, |
||||
directives: ['ClosePopup'], |
||||
plugins: ['Notify'], |
||||
config: { |
||||
notify: { |
||||
position: 'top', |
||||
multiLine: true, |
||||
timeout: 0, |
||||
}, |
||||
}, |
||||
loading: {}, // default set of options for Loading Quasar plugin |
||||
loadingBar: {}, // settings for LoadingBar Quasar plugin |
||||
}*/ |
||||
</script> |
||||
|
||||
{{ encore_entry_script_tags('vue') }} |
||||
{% endblock %} |
Loading…
Reference in new issue