Document: Add template list and tinyMCE integration - refs #3804

pull/5113/head
christianbeeznst 2 years ago
parent 07e699a0e5
commit 6a9a382afb
  1. 57
      assets/css/app.scss
  2. 10
      assets/vue/components/documents/FormNewDocument.vue
  3. 26
      assets/vue/components/documents/TemplateList.vue
  4. 44
      assets/vue/views/documents/CreateFile.vue
  5. 57
      assets/vue/views/documents/UpdateFile.vue
  6. 2
      public/main/admin/settings.php
  7. 6
      src/CoreBundle/Controller/Admin/IndexBlocksController.php
  8. 33
      src/CoreBundle/Controller/TemplateController.php
  9. 3
      src/CoreBundle/Entity/SystemTemplate.php
  10. 19
      src/CoreBundle/Repository/SystemTemplateRepository.php

@ -520,6 +520,63 @@ table#skill_holder {
justify-content: center;
}
.documents-layout {
display: flex;
justify-content: space-between;
}
.template-list-container {
flex-basis: 20%;
max-height: 600px;
overflow-y: auto;
}
.documents-form-container {
flex-basis: 78%;
}
.template-item img {
border: 1px solid #ccc;
box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.2);
border-radius: 4px;
transition: transform 0.2s ease;
}
.template-item img:hover {
transform: scale(1.05);
cursor: pointer;
}
.template-list {
display: flex;
flex-direction: column;
gap: 10px;
}
.template-item {
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
padding: 10px;
border: 1px solid #ccc;
border-radius: 4px;
background-color: #f9f9f9;
}
.template-item img {
width: 100%;
max-width: 200px;
height: auto;
object-fit: cover;
border-radius: 4px;
margin-bottom: 5px;
}
.template-item:hover {
background-color: #ececec;
cursor: pointer;
}
//@import 'primevue-md-light-indigo/theme.css';
//@import '~primevue/resources/primevue.min.css';

@ -87,11 +87,16 @@ export default {
data() {
return {
title: null,
contentFile: null,
contentFile: this.initialValues ? this.initialValues.contentFile : '',
parentResourceNodeId: null,
resourceNode: null,
};
},
watch: {
contentFile(newContent) {
tinymce.get('item_content').setContent(newContent);
}
},
computed: {
item() {
return this.initialValues || this.values;
@ -180,6 +185,9 @@ export default {
);
return false;
},
updateContent(content) {
this.contentFile = content;
},
},
validations: {
item: {

@ -0,0 +1,26 @@
<template>
<div class="template-list">
<div
v-for="template in templates"
:key="template.id"
class="template-item"
@click="selectTemplate(template.content)">
<img :src="template.image" />
<div>{{ template.title }}</div>
</div>
</div>
</template>
<script>
export default {
name: 'TemplateList',
props: {
templates: []
},
methods: {
selectTemplate(content) {
this.$emit('template-selected', content);
},
}
}
</script>

@ -3,11 +3,23 @@
:handle-reset="resetForm"
:handle-submit="onSendFormData"
/>
<DocumentsForm
ref="createForm"
:errors="violations"
:values="item"
/>
<div class="documents-layout">
<div class="template-list-container">
<TemplateList
:templates="templates"
@template-selected="addTemplateToEditor"
/>
</div>
<div class="documents-form-container">
<DocumentsForm
ref="createForm"
:errors="violations"
:values="item"
/>
</div>
</div>
<Panel
v-if="$route.query.cert === '1'"
:header="$t('Create your certificate copy-pasting the following tags. They will be replaced in the document by their student-specific value:')"
@ -26,6 +38,8 @@ import Toolbar from "../../components/Toolbar.vue"
import CreateMixin from "../../mixins/CreateMixin"
import { RESOURCE_LINK_PUBLISHED } from "../../components/resource_links/visibility"
import Panel from "primevue/panel"
import TemplateList from "../../components/documents/TemplateList.vue"
import axios from "axios"
const servicePrefix = "Documents"
@ -38,6 +52,7 @@ export default {
name: "DocumentsCreateFile",
servicePrefix,
components: {
TemplateList,
Loading,
Toolbar,
DocumentsForm,
@ -55,6 +70,7 @@ export default {
resourceLinkList: null,
contentFile: null,
},
templates: [],
finalTags,
};
},
@ -74,6 +90,19 @@ export default {
},
methods: {
addTemplateToEditor(templateContent) {
this.item.contentFile = templateContent;
},
fetchTemplates() {
axios.get('/system-templates')
.then(response => {
console.log(response.data);
this.templates = response.data;
})
.catch(error => {
console.error('There was an error fetching the templates:', error);
});
},
getCertificateTags(){
let finalTags = "";
let tags = [
@ -107,6 +136,9 @@ export default {
return finalTags;
},
...mapActions('documents', ['createWithFormData', 'reset'])
}
},
mounted() {
this.fetchTemplates();
},
};
</script>

@ -5,17 +5,27 @@
:handle-reset="resetForm"
:handle-submit="onSendFormData"
/>
<DocumentsForm
ref="updateForm"
:errors="violations"
:values="item"
>
<EditLinks
:item="item"
:show-share-with-user="false"
links-type="users"
/>
</DocumentsForm>
<div class="documents-layout">
<div class="template-list-container">
<TemplateList
:templates="templates"
@template-selected="addTemplateToEditor"
/>
</div>
<div class="documents-form-container">
<DocumentsForm
ref="updateForm"
:errors="violations"
:values="item"
>
<EditLinks
:item="item"
:show-share-with-user="false"
links-type="users"
/>
</DocumentsForm>
</div>
</div>
<Loading :visible="isLoading || deleteLoading" />
</div>
@ -29,6 +39,8 @@ import Loading from "../../components/Loading.vue"
import Toolbar from "../../components/Toolbar.vue"
import UpdateMixin from "../../mixins/UpdateMixin"
import EditLinks from "../../components/resource_links/EditLinks.vue"
import TemplateList from "../../components/documents/TemplateList.vue"
import axios from "axios";
const servicePrefix = "Documents"
@ -36,11 +48,17 @@ export default {
name: "DocumentsUpdate",
servicePrefix,
components: {
TemplateList,
EditLinks,
Loading,
Toolbar,
DocumentsForm,
},
data() {
return {
templates: [],
};
},
mixins: [UpdateMixin],
computed: {
...mapFields("documents", {
@ -56,6 +74,20 @@ export default {
}),
},
methods: {
fetchTemplates() {
axios.get('/system-templates')
.then(response => {
this.templates = response.data;
})
.catch(error => {
console.error('Error fetching the templates:', error);
});
},
addTemplateToEditor(templateContent) {
if (this.$refs.updateForm && typeof this.$refs.updateForm.updateContent === 'function') {
this.$refs.updateForm.updateContent(templateContent);
}
},
...mapActions("documents", {
createReset: "resetCreate",
deleteItem: "del",
@ -65,5 +97,8 @@ export default {
updateReset: "resetUpdate",
}),
},
mounted() {
this.fetchTemplates();
},
}
</script>

@ -33,7 +33,7 @@ api_protect_admin_script();
$table_settings_current = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
// Setting breadcrumbs.
$interbreadcrumb[] = ['url' => 'index.php', 'name' => get_lang('Administration')];
$interbreadcrumb[] = ['url' => api_get_path(WEB_PATH).'admin', 'name' => get_lang('Administration')];
// Setting the name of the tool.
$tool_name = get_lang('Configuration settings');

@ -457,6 +457,12 @@ class IndexBlocksController extends BaseController
'label' => $this->translator->trans('Contact categories'),
];
$items[] = [
'class' => 'item-system-template-admin',
'url' => $this->generateUrl('legacy_main', ['name' => 'admin/settings.php', 'category' => 'Templates']),
'label' => $this->translator->trans('System Templates'),
];
return $items;
}

@ -0,0 +1,33 @@
<?php
declare(strict_types=1);
/* For licensing terms, see /license.txt */
namespace Chamilo\CoreBundle\Controller;
use Chamilo\CoreBundle\Repository\AssetRepository;
use Chamilo\CoreBundle\Repository\SystemTemplateRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Routing\Annotation\Route;
class TemplateController extends AbstractController
{
#[Route('/system-templates', name: 'system-templates')]
public function getTemplates(SystemTemplateRepository $templateRepository, AssetRepository $assetRepository): JsonResponse
{
$templates = $templateRepository->findAll();
$data = array_map(function ($template) use ($assetRepository) {
return [
'id' => $template->getId(),
'title' => $template->getTitle(),
'comment' => $template->getComment(),
'content' => $template->getContent(),
'image' => $template->getImage() ? $assetRepository->getAssetUrl($template->getImage()) : null,
];
}, $templates);
return $this->json($data);
}
}

@ -6,13 +6,14 @@ declare(strict_types=1);
namespace Chamilo\CoreBundle\Entity;
use Chamilo\CoreBundle\Repository\SystemTemplateRepository;
use Doctrine\ORM\Mapping as ORM;
/**
* SystemTemplate.
*/
#[ORM\Table(name: 'system_template')]
#[ORM\Entity]
#[ORM\Entity(repositoryClass: SystemTemplateRepository::class)]
class SystemTemplate
{
#[ORM\Column(name: 'id', type: 'integer')]

@ -0,0 +1,19 @@
<?php
declare(strict_types=1);
/* For licensing terms, see /license.txt */
namespace Chamilo\CoreBundle\Repository;
use Chamilo\CoreBundle\Entity\SystemTemplate;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
class SystemTemplateRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, SystemTemplate::class);
}
}
Loading…
Cancel
Save