svg
Cadoles/nineskeletor/pipeline/head There was a failure building this commit Details

This commit is contained in:
afornerot 2024-07-27 09:15:34 +02:00
parent 671b37197e
commit 6a5e14a25e
16 changed files with 460 additions and 19 deletions

8
.env
View File

@ -3,6 +3,10 @@ APP_ENV=dev
APP_SECRET=changeme
APP_SESSIONTIME=1440
# Webpack
APP_PUBLIC_PATH=/nineskeletor/build
APP_MANIFEST_KEY_PREFIX=nineskeletor
# Messenger
MESSENGER_TRANSPORT_DSN=doctrine://default?auto_setup=0
@ -96,8 +100,8 @@ LDAP_GROUPGID=gidnumber # Attribut gid d
LDAP_GROUPNAME=cn # Attribut name d'un groupe
LDAP_GROUPMEMBER=memberuid # Attribut stockant les membres d'un groupe
LDAP_GROUPMEMBERISDN=0 # LDAP_GROUPMEMBER stocke un uid ou un dn ? 0/1
LDAP_FILTERGROUP=(cn=*) # requete ldap pour rechercher les groupes
LDAP_FILTERUSER=(uid=*) # requete ldap pour rechercher les users
LDAP_FILTERGROUP="(cn=*)" # requete ldap pour rechercher les groupes
LDAP_FILTERUSER="(uid=*)" # requete ldap pour rechercher les users
LDAP_AUTOSUBMIT=1 # if APP_AUTH = LDAP autocréer les users non existant
LDAP_AUTOUPDATE=1 # if APP_AUTH = LDAP automodifier les users existant

View File

@ -1608,6 +1608,32 @@ app_all_pagewidget_view_groupmessage:
controller: App\Controller\PagewidgetController::viewgroupmessage
defaults: { access: all }
#== DOCUMENT ================================================================================================================
#-- Access admin
app_admin_document:
path: /admin/document
controller: App\Controller\DocumentController::list
defaults: { access: admin }
app_admin_document_submit:
path: /admin/document/submit
controller: App\Controller\DocumentController::submit
defaults: { access: admin }
app_admin_document_update:
path: /admin/document/update/{id}
controller: App\Controller\DocumentController::update
defaults: { access: admin }
app_admin_document_delete:
path: /admin/document/delete/{id}
controller: App\Controller\DocumentController::delete
app_admin_document_render:
path: /admin/document/render/{idcategory}
controller: App\Controller\DocumentController::renderid
defaults: { access: admin }
#== DOCUMENTCATEGORY ========================================================================================================
#-- Access admin
app_admin_documentcategory:

View File

@ -1,14 +1,14 @@
FROM reg.cadoles.com/envole/nineapache:8.1
COPY ./misc/docker/apache.conf /etc/apache2/conf.d/nine/site.conf
RUN echo "* * * * * /app/bin/console app:Cron --env=prod" >> /var/spool/cron/crontabs/root
WORKDIR /app
COPY . .
RUN yarn install
RUN yarn encore dev
RUN yarn encore prod
# Installation des dépendances composer
RUN composer install --no-interaction
RUN mkdir -p /app/public/uploads
RUN chown apache /app/public/uploads -R
@ -18,5 +18,4 @@ RUN mkdir -p /app/var
RUN chown apache /app/var -R
RUN chmod u+w /app/var -R
CMD /app/misc/script/reconfigure.sh && /etc/apache2/apache2.sh
#CMD /etc/apache2/apache2.sh
CMD /app/misc/script/reconfigure.sh && /etc/apache2/apache2.sh

19
misc/docker/apache.conf Executable file
View File

@ -0,0 +1,19 @@
LoadModule rewrite_module modules/mod_rewrite.so
ServerName nineapache.local
DocumentRoot "/app/public"
Alias /nineskeletor /app/public
<Directory "/app/public">
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
RewriteEngine On
RewriteCond %{REQUEST_URI}::$0 ^(/.+)/(.*)::\2$
RewriteRule .* - [E=BASE:%1]
RewriteCond %{HTTP:Authorization} .+
RewriteRule ^ - [E=HTTP_AUTHORIZATION:%0]
RewriteCond %{ENV:REDIRECT_STATUS} =""
RewriteRule ^index\.php(?:/(.*)|$) %{ENV:BASE}/$1 [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ %{ENV:BASE}/index.php [L]
</Directory>

View File

@ -7,11 +7,21 @@ cd ${DIR}
cd ../..
DIR=$(pwd)
# Installation des dépendances composer
composer install --no-interaction
bin/console d:s:u --force --complete
# Si l'alias courrant est différent que celui généré = on compile encore
last_alias=""
if [ -f .alias ]; then
last_alias=$(cat .alias)
fi
if [ "$APP_MANIFEST_KEY_PREFIX" != "$last_alias" ]; then
echo "Alias a changé. Recompilation nécessaire."
echo "$APP_MANIFEST_KEY_PREFIX" > .alias
yarn encore dev
yarn encore prod
fi
bin/console app:Init
exec $@

View File

@ -25,6 +25,7 @@
"ckeditor4": "^4.19.0",
"crop-select-js": "^1.0.1",
"datatables.net-bs4": "^1.12.1",
"dotenv": "^16.4.5",
"dropzone": "^6.0.0-beta.2",
"file-loader": "^6.2.0",
"iframe-resizer": "^4.3.2",

View File

@ -0,0 +1,137 @@
<?php
namespace App\Controller;
use App\Entity\Document;
use App\Form\DocumentType;
use Doctrine\Persistence\ManagerRegistry;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
class DocumentController extends AbstractController
{
private $data = 'document';
private $entity = "App\Entity\Document";
private $twig = 'Document/';
private $route = 'app_admin_document';
public function list($access, ManagerRegistry $em): Response
{
$documentcategorys = $em->getRepository("App\Entity\Documentcategory")->findBy(['parent' => null], ['roworder' => 'ASC']);
$datas = $em->getRepository("App\Entity\Document")->findAll(['documentcategory' => null], ['roworder' => 'ASC']);
return $this->render($this->twig.'list.html.twig', [
'useheader' => true,
'usemenu' => false,
'usesidebar' => ('admin' == $access),
'access' => $access,
'documentcategorys' => $documentcategorys,
$this->data.'s' => $datas,
]);
}
public function submit($access, Request $request, ManagerRegistry $em): Response
{
// Initialisation de l'enregistrement
$data = new Document();
$data->setRoworder(0);
// Création du formulaire
$form = $this->createForm(DocumentType::class, $data, ['mode' => 'submit', 'access' => $access]);
// Récupération des data du formulaire
$form->handleRequest($request);
// Sur validation
if ($form->get('submit')->isClicked() && $form->isValid()) {
$data = $form->getData();
// Sauvegarde
$em->getManager()->persist($data);
$em->getManager()->flush();
// Retour à la liste
return $this->redirectToRoute(str_replace('_admin_', '_'.$access.'_', $this->route));
}
// Affichage du formulaire
return $this->render($this->twig.'edit.html.twig', [
'useheader' => true,
'usemenu' => false,
'usesidebar' => ('admin' == $access),
'access' => $access,
$this->data => $data,
'mode' => 'submit',
'form' => $form->createView(),
]);
}
public function update($id, $access, Request $request, ManagerRegistry $em): Response
{
// Initialisation de l'enregistrement
$data = $em->getRepository($this->entity)->find($id);
if (!$data) {
throw $this->createNotFoundException('Unable to find entity.');
}
// Création du formulaire
$form = $this->createForm(DocumentType::class, $data, ['mode' => 'update']);
// Récupération des data du formulaire
$form->handleRequest($request);
// Sur validation
if ($form->get('submit')->isClicked() && $form->isValid()) {
$data = $form->getData();
// Sauvegarde
$em->getManager()->flush();
// Retour à la liste
return $this->redirectToRoute(str_replace('_admin_', '_'.$access.'_', $this->route));
}
// Affichage du formulaire
return $this->render($this->twig.'edit.html.twig', [
'useheader' => true,
'usemenu' => false,
'usesidebar' => ('admin' == $access),
'access' => $access,
$this->data => $data,
'mode' => 'update',
'form' => $form->createView(),
]);
}
public function delete($id, $access, Request $request, ManagerRegistry $em): Response
{
// Initialisation de l'enregistrement
$data = $em->getRepository($this->entity)->find($id);
if (!$data) {
throw $this->createNotFoundException('Unable to find entity.');
}
// Tentative de suppression
try {
$em->getManager()->remove($data);
$em->getManager()->flush();
} catch (\Exception $e) {
$request->getSession()->getFlashBag()->add('error', $e->getMessage());
return $this->redirectToRoute($this->route.'_update', ['id' => $id]);
}
return $this->redirectToRoute(str_replace('_admin_', '_'.$access.'_', $this->route));
}
public function renderid($idcategory, $access, ManagerRegistry $em): Response
{
$data = $em->getRepository("App\Entity\Documentcategory")->find($idcategory);
return $this->render($this->twig.'render.html.twig', [
'access' => $access,
'documentcategory' => $data,
]);
}
}

View File

@ -24,7 +24,7 @@ class DocumentcategoryController extends AbstractController
return $this->render($this->twig.'list.html.twig', [
'useheader' => true,
'usemenu' => false,
'usesidebar' => true,
'usesidebar' => ('admin' == $access),
'access' => $access,
$this->data.'s' => $datas,
]);
@ -68,7 +68,7 @@ class DocumentcategoryController extends AbstractController
return $this->render($this->twig.'edit.html.twig', [
'useheader' => true,
'usemenu' => false,
'usesidebar' => true,
'usesidebar' => ('admin' == $access),
'access' => $access,
$this->data => $data,
'mode' => 'submit',
@ -105,7 +105,7 @@ class DocumentcategoryController extends AbstractController
return $this->render($this->twig.'edit.html.twig', [
'useheader' => true,
'usemenu' => false,
'usesidebar' => true,
'usesidebar' => ('admin' == $access),
'access' => $access,
$this->data => $data,
'mode' => 'update',

View File

@ -52,9 +52,19 @@ class Documentcategory
*/
private $childs;
/**
* @var ArrayCollection
* @var Document
*
* @ORM\OneToMany(targetEntity="Document", mappedBy="documentcategory", cascade={"persist"}, orphanRemoval=false)
* @ORM\OrderBy({"roworder" = "ASC"})
*/
private $documents;
public function __construct()
{
$this->childs = new ArrayCollection();
$this->documents = new ArrayCollection();
}
public function getId(): ?int
@ -127,4 +137,34 @@ class Documentcategory
return $this;
}
/**
* @return Collection<int, Document>
*/
public function getDocuments(): Collection
{
return $this->documents;
}
public function addDocument(Document $document): self
{
if (!$this->documents->contains($document)) {
$this->documents->add($document);
$document->setDocumentcategory($this);
}
return $this;
}
public function removeDocument(Document $document): self
{
if ($this->documents->removeElement($document)) {
// set the owning side to null (unless already changed)
if ($document->getDocumentcategory() === $this) {
$document->setDocumentcategory(null);
}
}
return $this;
}
}

37
src/Form/DocumentType.php Executable file
View File

@ -0,0 +1,37 @@
<?php
namespace App\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class DocumentType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('submit',
SubmitType::class, [
'label' => 'Valider',
'attr' => ['class' => 'btn btn-success'],
]
);
$builder->add('label',
TextType::class, [
'label' => 'Label',
]
);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => 'App\Entity\Document',
'access' => 'string',
'mode' => 'string',
]);
}
}

View File

@ -0,0 +1,62 @@
{% extends 'base.html.twig' %}
{% block body %}
{{ form_start(form) }}
<h1 class="page-header">
{% if mode=="update" %}
Modification Catégorie de Document = {{document.label}}
{% elseif mode=="submit" %}
Création Catégorie de Document
{% endif %}
</h1>
{{ form_widget(form.submit) }}
<a class="btn btn-secondary" href={{ path('app_admin_document') }}>Annuler</a>
{% if mode=="update" %}
<a class="btn btn-danger float-end" href={{ path('app_admin_document_delete',{id:document.id}) }} data-method="delete" data-confirm="Êtes-vous sûr de vouloir supprimer cet enregistrement ?">Supprimer</a>
{% endif %}
{% if app.session.flashbag.has('error') %}
<div class='alert alert-danger' style='margin: 5px 0px'>
<strong>Erreur</strong><br>
{% for flashMessage in app.session.flashbag.get('error') %}
{{ flashMessage }}<br>
{% endfor %}
</div>
{% endif %}
{% if app.session.flashbag.has('notice') %}
<div class='alert alert-info' style='margin: 5px 0px'>
<strong>Information</strong><br>
{% for flashMessage in app.session.flashbag.get('notice') %}
{{ flashMessage }}<br>
{% endfor %}
</div>
{% endif %}
<div class="card mt-4">
<div class="card-header">
<i class="fa fa-pencil-alt fa-fw"></i> Informations
</div>
<div class="card-body">
{{ form_row(form.label) }}
</div>
</div>
{% if auditUse and mode=="update" and (access=="admin" or access=="modo" or access=="audit") %}
<div class="float-end" style="width:700px;max-width:100%">
{{ render(path("app_"~access~"_audit_renderid",{entityname:"Document",entityid:document.id})) }}
</div>
{% endif %}
{{ form_end(form) }}
{% endblock %}
{% block localscript %}
<script>
$('document').ready(function(){
$("#document_label").focus();
});
</script>
{% endblock %}

View File

@ -0,0 +1,66 @@
{% extends 'base.html.twig' %}
{% block localstyle %}
<style>
.item-action .btn-modal {
color: inherit;
}
</style>
{% endblock %}
{% block body %}
<h1 class="page-header">Gestion des Documents </h1>
<a class="btn btn-success" href="{{ path('app_'~access~'_document_submit') }}">Ajouter</a>
{% if auditUse and (access=="admin" or access=="audit") %}
<a class="btn btn-secondary float-end" href="{{ path('app_'~access~'_audit_render',{entityname:'Document'}) }}"><i class="fas fa-eye fa-fw"></i> Audit</a>
{% endif %}
</p>
<div class="card mt-4">
<div class="card-header">
<i class="fa fa-table fa-fw"></i> Liste des Catégories de Document
</div>
<div class="card-body">
<div class="item-list">
{% for documentcategory in documentcategorys %}
{{ render(path("app_"~access~"_document_render",{idcategory:documentcategory.id})) }}
{% endfor %}
</div>
{% for document in documents %}
<div class="item item-list" style="background-color: var(--colorbgbodydark);">
<div class="item-container">
<div class="item-content">
<div class="item-link">
<img height="35" src="/medias/file/blank.png">
<div class="item-title">
<h3>{{ document.label }}</h3>
</div>
</div>
<div class="item-action">
<a style="display: none;" class="btn-modal" href="{{path('app_'~access~'_document_update',{id:document.id})}}">
<i class="fas fa-file"></i>
</a>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
{% endblock %}
{% block localscript %}
<script>
</script>
{% endblock %}

View File

@ -0,0 +1,29 @@
<div class="item item-list" style="background-color: var(--colorbgbodydark);">
<div class="item-container">
<div class="item-content">
<div class="item-link">
<img height="35" src="/medias/file/dir.png">
<div class="item-title">
<h3>{{ documentcategory.label }}</h3>
</div>
</div>
</div>
</div>
<div class="item-childs" style="width:100%">
{% if not documentcategory.childs is empty %}
{% for documentcategory in documentcategory.childs %}
{% if loop.first %}<div style="height:5px">&nbsp;</div>{%endif%}
{{ render(path("app_"~access~"_document_render",{idcategory:documentcategory.id,access:access})) }}
{% endfor %}
{% endif %}
{% if not documentcategory.documents is empty %}
{% for document in documentcategory.documents %}
{% endfor %}
{% endif %}
</div>
</div>

View File

@ -101,6 +101,11 @@
'icon': 'fa fa-file fa-fw',
'name' : 'DOCUMENTS',
'items' : [
{
icon: 'fa fa-cogs',
route: 'app_admin_document',
name: 'Documents',
},
{
icon: 'fa fa-cogs',
route: 'app_admin_documentcategory',
@ -134,7 +139,7 @@
{% for section in sidebar %}
{% set sectionactive=false %}
{% for item in section.items %}
{% if item.route in app.request.get('_route') %}
{% if item.route==app.request.get('_route') or (item.route~"_") in app.request.get('_route') %}
{% set sectionactive=true %}
{% endif %}
{% endfor %}
@ -161,7 +166,7 @@
{% if item.route=="app_admin_group" and not appGroupuse %} {% set toshow=false %} {% endif %}
{%if toshow %}
<a class="nav-link nav-link-item {% if item.route in app.request.get('_route') %}active{%endif%}" href="{{path(item.route)}}" title="{{item.name}}">
<a class="nav-link nav-link-item {% if item.route==app.request.get('_route') or (item.route~'_') in app.request.get('_route') %}active{%endif%}" href="{{path(item.route)}}" title="{{item.name}}">
<i class="{{item.icon}} fa-fw"></i>
<span>{{item.name}}</span>
</a>

View File

@ -1,4 +1,6 @@
const Encore = require('@symfony/webpack-encore');
const dotenv = require('dotenv');
const path = require('path');
// Manually configure the runtime environment if not already configured yet by the "encore" command.
// It's useful when you use tools that rely on webpack.config.js file.
@ -10,9 +12,8 @@ Encore
// directory where compiled assets will be stored
.setOutputPath('public/build/')
// public path used by the web server to access the output path
.setPublicPath('/build')
// only needed for CDN's or sub-directory deploy
//.setManifestKeyPrefix('build/')
.setPublicPath(process.env.APP_PUBLIC_PATH || '/build')
.setManifestKeyPrefix(process.env.APP_MANIFEST_KEY_PREFIX || '')
/*
* ENTRY CONFIG

View File

@ -2449,6 +2449,11 @@ dot-prop@^5.1.0:
dependencies:
is-obj "^2.0.0"
dotenv@^16.4.5:
version "16.4.5"
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.5.tgz#cdd3b3b604cb327e286b4762e13502f717cb099f"
integrity sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==
dropzone@^6.0.0-beta.2:
version "6.0.0-beta.2"
resolved "https://registry.yarnpkg.com/dropzone/-/dropzone-6.0.0-beta.2.tgz#098be8fa84bdc08674cf0b74f4c889e2679083d6"