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