mise à niveau

This commit is contained in:
afornerot 2020-11-13 17:53:40 +01:00
parent 4fc12fb766
commit ba27cb51b3
31 changed files with 1457 additions and 558 deletions

225
README.md
View File

@ -1,224 +1,3 @@
# Renommer le squelette
## Dupliquer nineskeletor et renommer en nineXXXX
Puis effectuer les changement suivants
- Renommer db/nineskeletor-create-0.sql en db/nineXXXX-create-0.sql
- Modifier db/nineXXXX-create-0.sql et changer le nom de la base de données en nineXXXX
- Renommer dicos/90_nineskeletor.xml en dicos/90_nineXXXX.xml
- Modifier dicos/nineXXXX-nineXXXX.xml et remplacer tout les nineskeletor en nineXXXX
- Renommer logrotate/nineskeletor en logrotate/nineXXXX
- Modifier logrotate/nineXXXX et remplacer tout les nineskeletor en nineXXXX
- Renommer postservice/90-nineskeletor en postservice/90-nineXXXX
- Modifier postservice/90-nineXXXX et remplacer tout les nineskeletor en nineXXXX
- Renommer pretemplate/25-nineskeletor en pretemplate/25-nineXXXX
- Modifier pretemplate/25-nineXXXX et remplacer tout les nineskeletor en nineXXXX
- Renommer src/nineskeletor-1.0 en src/nineXXXX-1.0
- Modifier src/nineXXXX-1.0/webpack.config.js et remplacer tout les nineskeletor en nineXXXX
- Renommer sso/filtres/nineskeletor.ini en sso/filtres/nineXXXX.ini
- Renommer sso/filtres/nineskeletor_apps.ini en sso/filtres/nineXXXX_apps.ini
- Modifier sso/filtres/nineXXXX_apps.ini et remplacer tout les nineskeletor en nineXXXX
- Renommer tmpl/nineskeletor.cron en tmpl/nineXXXX.cron
- Modifier tmpl/nineXXXX.cron et remplacer tout les nineskeletor en nineXXXX
- Renommer tmpl/nineskeletor-apache.conf en tmpl/nineXXXX-apache.conf
- Modifier tmpl/nineXXXX-apache.conf et remplacer tout les nineskeletor en nineXXXX
- Renommer tmpl/nineskeletor-db.yml en tmpl/nineXXXX-db.yml
- Modifier tmpl/nineXXXX-db.yml et remplacer tout les nineskeletor en nineXXXX
- Renommer tmpl/nineskeletor-env.local en tmpl/nineXXXX-env.local
- Modifier tmpl/nineXXXX-env.local et remplacer tout les nineskeletor en nineXXXX
- Renommer tmpl/nineskeletor-proxy.sh en tmpl/nineXXXX-proxy.sh
- Modifier Makefile et remplacer tout les nineskeletor en nineXXXX
- Remplacer logo public/images/logo.png
# Prototype Ninesurvey
Une alternative à Opensondage
## Compilier les asset
- installer nodejs
- installer npm
- installer n
- passer sur la verison 8 de node
- yarn encore dev
- yarn encore prod
# Description du squelette
## Bundle
- DebugBundle
- DoctrineBundle
- DoctrineMigrationsBundle
- FOSCKEditorBundle
- FOSRestBundle
- FrameworkBundle
- KnpSnappyBundle
- MakerBundle
- MonologBundle
- NelmioApiDocBundle
- OneupUploaderBundle
- SecurityBundle
- SensioFrameworkExtraBundle
- SwiftmailerBundle
- TetranzSelect2EntityBundle
- TwigBundle
- TwigExtraBundle
- WebProfilerBundle
- WebpackEncoreBundle
## Asset
### Tag app
- jQuery = https://www.npmjs.com/package/jquery
- bootstrap = https://www.npmjs.com/package/bootstrap
- datatables.net-bs4 = https://www.npmjs.com/package/datatables.net-bs4
- fontawsome-free = https://www.npmjs.com/package/@fortawesome/fontawesome-free
- moment = https://www.npmjs.com/package/moment
- select2 = https://www.npmjs.com/package/select2
- crop-select-js = https://www.npmjs.com/package/crop-select-js
- tempusdominus-bootstrap-4 = https://www.npmjs.com/package/tempusdominus-bootstrap-4
- spectrum-colorpicker2 = https://www.npmjs.com/package/spectrum-colorpicker2
### Tag morris
- raphael = https://www.npmjs.com/package/raphael
- morris.js = https://www.npmjs.com/package/morris.js
### Tag fullcalendar
- @fullcalendar/core = https://www.npmjs.com/package/@fullcalendar/core
- @fullcalendar/interaction = https://www.npmjs.com/package/@fullcalendar/interaction
- @fullcalendar/daygrid = https://www.npmjs.com/package/@fullcalendar/daygrid
### Tag dropzone
- dropzone = https://www.npmjs.com/package/dropzone
## Parameters
Provient du template env.local
- appEnv = PROD
- appSecret = valeur du fichier .key autogénéré au premier reconfigure
- appWeburl = Valeur du dicos web_url
- appAuth = Valeur du dicos CAS
- appAlias = En dur l'alias web
- appName = Nom de l'application
- appCron = En dur à true pour activer le système de cron
- appMasteridentity = Valeur du dicos soit Ninegate soit LDAP
- appMasterurl = Si appMasteridentity la valeur du dicos correspondant à l'url du Ninegate maître
- appMasterkey = Si appMasteridentity la valeur du dicos correspondant à la clé d'API du Ninegate maître
- databaseName = En dur le nom de la base
- databaseUser = En dur le user de la base
- databasePassword = Autogénéré par le reconfigure
- databaseHost = Valeur du dicos pour le host de la base
- appMailmethod = Valeur du dicos soit sendmail soit smtp. sendmail par défaut si exim est activé sur le serveur
- appMailurl = Si smtp url calculé combinant smtphost smtpport smtpencryption smtpauthmode smtpuser smtppwd
- appMailnoreply = Valeur du dicos du noreplay
- ldapModel = si masteridentity à LDAP soit open soit scribe
- ldapHost = Valeur dicos Host LDAP
- ldapPort = Valeur dicos Port LDAP
- ldapUser = Valeur dicos User LDAP
- ldapPassword = Valeur dicos Password LDAP
- ldapBasedn = Valeur dicos Basedn LDAP
- ldapUsername = si Scribe en dur sinon valeur du dicos champs annuaire utilisé comme username
- ldapFirstname = si Scribe en dur sinon valeur du dicos champs annuaire utilisé comme firstname
- ldapLastname = si Scribe en dur sinon valeur du dicos champs annuaire utilisé comme lastname
- ldapEmail = si Scribe en dur sinon valeur du dicos champs annuaire utilisé comme email
- ldapFiltergroup = si Scribe en dur sinon valeur du dicos filtre ldap de recherche des groupes
- ldapFilteruser = si Scribe en dur sinon valeur du dicos filtre ldap des groupes
- ldapAdmins = Liste des admins obligatoire = Admin + valeur dicos
- casHost = Valeur dicos du host SSO
- casPort = Valeur dicos du Porst SSO
- casPath = Valeur dicos du Path SSO
- casUsername = Valeur en dur correspondant au filtre sso du username
- casEmail = Valeur en dur correspondant au filtre sso du email
- casLastname = Valeur en dur correspondant au filtre sso du lastname
- casFirstname = Valeur en dur correspondant au filtre sso du fistname
- proxyUse = Valeur dicos utiliser oui/non un proxy
- proxyHost = Si oui valeurs du dicos du host proxy
- proxyPort = Si oui valeurs du dicos du post proxy
- sondeUse = Valeur dicos utiliser oui/non une sonde statistique
- sondeUrl = Si oui url de la sonde statistique
## Sécurité
4 rôles possibles
- ROLE_ADMIN
- ROLE_MODO
- ROLE_MASTER
- ROLE_USER
4 routes protégés
- /user = accèssible à ROLE_USER / ROLE_MASTER / ROLE_MODO / ROLE_ADMIN
- /master = accèssible à ROLE_MASTER / ROLE_MODO / ROLE_ADMIN
- /modo = = accèssible à ROLE_MODO / ROLE_ADMIN
- /admin = = accèssible à ROLE_ADMIN
## Job
Nineskeletor intègre un système de job.
Ce système va exécuter des commandes symfony à interval régulier.
De base les jobs suivants sont livrés :
- app:sendMail = toutes les minutes = Execution du spool de mail en attente
- app:dumpBdd = toutes les nuits à 2h00 = Dump de la base
- app:purgeFile = toutes les nuits à 3h00 = Suppresion des fichiers obsolètes
- app:synchroUsers = toutes les nuites à 3h00 = Synchronisation des comptes utilisateurs soit via LDAP soit via Ninegate
Pour ajouter un job à la listes, modifier la commande app:initCron qui sera exécutée à chaque reconfigure
## Service
- app.password.encoder = encodage password sur la methode que l'annuaire
- app.upload.listener = action à réaliser sur upload via oneupload
- app.upload.samename = permet d'uploader un fichier et préserver le nom de fichier via oneupload
- app.ldap.service = fonction ldap
- app.sendmail.transport = executuion du spool de mail via sendmail
- app.mail.service = fonction envoit de mail
- app.twig.extension = extention twig
## Twig
### Twig Constantes
Variables globales twig reprises des parametres symfony
- appAlias
- appAuth
- appName
- appCron
- appMasteridentity
- sondeUse
- sondeUrl
### Twig Extention
App\Twig\AppExtension
- filtre = urlAvatar à placer avec user.avatar afin de définir l'url complète de l'avatar du user
### Twig Template de base
#### templates/base.html.twig
Deux paramétres non obligatoire
- useheader = permet d'afficher ou non la bannière dans la page = false par défaut
- usesidebar = permet d'afficher oun non la sidebar dans la page = false par défaut
Block
- block encorelinktags = pour déclarer des encore_link_tags spécifique à la page (encorelinktags app est intégré de base)
- block localstyle = pour déclarer des propriétés css spécifique à page (Include/style.css.twig est intégré de base)
- block body = le corps de la page
- block encorescripttags pour déclarer des encore_script_tags spécifique à la page (encorescripttags app est intégré de base)
- block localjavascript = pour déclarer du js spécifique à la page (Include/javascript.js.twig est intégré de base)
#### templates/Include/style.css.twig
Style de l'applicaiton en surcouche de bootstrap
#### templates/Include/sidebar.html.twig
La sidebar de l'application quand elle est affichée
#### templates/Include/javascript.js.twig
Librairie js de l'application
- object a et button s'ils ont un attribut data-method et data_confirm proposeront une confirmation à l'utilisateur avant de poursuivre l'action
- ModalLoad(idmodal,titre,url) = permet d'afficher en modal l'url indiqué en parametre. Par défaut on dispose de la modal #mymodal
#### templates/Form/fields.htms.twig
Mise en forme de champs de formulaire

View File

@ -29,4 +29,7 @@ yarn-error.log
!/public/uploads/avatar/admin.jpg
!/public/uploads/avatar/noavatar.jpg
!/public/uploads/avatar/system.jpg
!/public/uploads/avatar
/public/uploads/logo/*
!/public/uploads/logo/logo.png
/public/uploads/ckeditor

View File

@ -2,6 +2,8 @@ oneup_uploader:
mappings:
avatar:
frontend: dropzone
logo:
frontend: dropzone
document:
frontend: dropzone
namer: app.upload.samename

View File

@ -28,6 +28,31 @@ app_logoutcas:
path: /logoutcas
defaults: { _controller: App\Controller\SecurityController:logout }
#== Config ========================================================================================================
app_config:
path: /admin/config
defaults: { _controller: App\Controller\ConfigController:list }
app_config_render:
path: /admin/config/render/{category}
defaults: { _controller: App\Controller\ConfigController:listrender }
app_config_submit:
path: /admin/config/submit
defaults: { _controller: App\Controller\ConfigController:submit }
app_config_update:
path: /admin/config/update/{id}
defaults: { _controller: App\Controller\ConfigController:update }
app_config_delete:
path: /admin/config/delete/{id}
defaults: { _controller: App\Controller\ConfigController:delete }
app_config_logo:
path: /admin/config/logo
defaults: { _controller: App\Controller\ConfigController:logo }
#== Sonde ================================================================================================================
app_sonde:
path: /sonde
@ -35,11 +60,11 @@ app_sonde:
#== Crop =========================================================================================================
app_crop01:
path: /user/crop01
path: /user/crop01/{type}/{reportinput}
defaults: { _controller: App\Controller\CropController:crop01 }
app_crop02:
path: /user/crop02
path: /user/crop02/{type}/{reportinput}
defaults: { _controller: App\Controller\CropController:crop02 }
oneup_uploader:
@ -76,10 +101,18 @@ app_user:
path: /admin/user
defaults: { _controller: App\Controller\UserController:list }
app_user_submit:
path: /admin/user/submit
defaults: { _controller: App\Controller\UserController:submit }
app_user_update:
path: /admin/user/update/{id}
defaults: { _controller: App\Controller\UserController:update }
app_user_delete:
path: /admin/user/delete/{id}
defaults: { _controller: App\Controller\UserController:delete }
app_user_select:
path: /user/user/select
defaults: { _controller: App\Controller\UserController:select }

View File

@ -80,6 +80,13 @@ services:
# add more service definitions when explicit configuration is needed
# please note that last definitions always *replace* previous ones
app.session.init:
public: true
class: App\Service\sessionInit
arguments: ["@service_container","@doctrine.orm.entity_manager","@session",]
tags:
- { name: kernel.event_listener, event: kernel.request, method: onDomainParse }
app.password.encoder:
public: true
class: App\Service\passwordEncoder

View File

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

View File

@ -14,6 +14,8 @@ use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\Id\AssignedGenerator;
use App\Entity\User;
use App\Entity\Config;
class AppInitCommand extends Command
{
@ -56,6 +58,195 @@ class AppInitCommand extends Command
// Création du compte admin si non existant
$this->insertUser("admin","admin");
// colorbgbody = Couleur des fonds de page
$this->insertConfig(
1, // order
"site", // category
"appname", // id
"Titre de votre site", // title
"", // value
"string", // type,
true, // visible
true, // changeable
false, // required
"", // grouped
"Titre de votre site"
);
$this->insertConfig(
2, // order
"site", // category
"appsubname", // id
"Sous-titre de votre site", // title
"", // value
"string", // type,
true, // visible
true, // changeable
false, // required
"", // grouped
"Sous-titre de votre site"
);
$this->insertConfig(
3, // order
"site", // category
"appdescription", // id
"Description de votre site", // title
"", // value
"editor", // type,
true, // visible
true, // changeable
false, // required
"", // grouped
"Description de votre site"
);
// colorbgbody = Couleur des fonds de page
$this->insertConfig(
1, // order
"colorbgbody", // category
"colorbgbodydark", // id
"Couleur de fond fonçée", // title
"", // value
"color", // type,
true, // visible
true, // changeable
false, // required
"", // grouped
"La couleur de fond quand le site a besoin d'avoir une couleur de fond foncée"
);
$this->insertConfig(
2, // order
"colorbgbody", // category
"colorbgbodylight", // id
"Couleur de fond claire", // title
"", // value
"color", // type,
true, // visible
true, // changeable
false, // required
"", // grouped
"La couleur de fond quand le site a besoin d'avoir une couleur de fond claire"
);
// colorfttitle = Couleur des fontes titre
$this->insertConfig(
1, // order
"colorfttitle", // category
"colorfttitledark", // id
"Couleur des titres sur fond fonçé", // title
"", // value
"color", // type,
true, // visible
true, // changeable
false, // required
"", // grouped
"La couleur des titres sur fond fonçé"
);
$this->insertConfig(
2, // order
"colorfttitle", // category
"colorfttitlelight", // id
"Couleur des titres sur fond claire", // title
"", // value
"color", // type,
true, // visible
true, // changeable
false, // required
"", // grouped
"La couleur des titres sur fond claire"
);
// colorftbody = Couleur des fontes titre
$this->insertConfig(
1, // order
"colorftbody", // category
"colorftbodydark", // id
"Couleur de la police sur fond fonçé", // title
"", // value
"color", // type,
true, // visible
true, // changeable
false, // required
"", // grouped
"La couleur de la police sur fond fonçé"
);
$this->insertConfig(
2, // order
"colorftbody", // category
"colorftbodylight", // id
"Couleur de la police sur fond claire", // title
"", // value
"color", // type,
true, // visible
true, // changeable
false, // required
"", // grouped
"La couleur de la police sur fond claire"
);
// font = nom des polices
$this->insertConfig(
1, // order
"font", // category
"fonttitle", // id
"Police pour les titres", // title
"", // value
"font", // type,
true, // visible
true, // changeable
false, // required
"", // grouped
"La couleur de la police de votre site"
);
$this->insertConfig(
2, // order
"font", // category
"fontbody", // id
"Police principale", // title
"", // value
"font", // type,
true, // visible
true, // changeable
false, // required
"", // grouped
"Nom de la police principale"
);
// logo =
$this->insertConfig(
1, // order
"logo", // category
"logodark", // id
"Logo sur fond fonçé", // title
"", // value
"logo", // type,
true, // visible
true, // changeable
false, // required
"", // grouped
"Logo sur fond fonçé"
);
$this->insertConfig(
2, // order
"logo", // category
"logolight", // id
"Logo sur fond clair", // title
"", // value
"logo", // type,
true, // visible
true, // changeable
false, // required
"", // grouped
"Logo sur fond clair"
);
$output->writeln('');
return 1;
@ -90,6 +281,28 @@ class AppInitCommand extends Command
}
protected function insertConfig($order,$category,$id,$title,$value,$type,$visible,$changeable,$required,$grouped,$help) {
$entity=$this->em->getRepository("App:Config")->find($id);
if(!$entity) {
$entity= new Config();
$entity->setId($id);
$entity->setValue($value);
}
$entity->setCategory($category);
$entity->setOrder($order);
$entity->setTitle($title);
$entity->setType($type);
$entity->setVisible($visible);
$entity->setChangeable($changeable);
$entity->setRequired($required);
$entity->setGrouped($grouped);
$entity->setHelp($help);
$this->em->persist($entity);
$this->em->flush();
}
private function writelnred($string) {
$this->output->writeln('<fg=red>'.$string.'</>');
$this->filesystem->appendToFile($this->rootlog.'cron.log', $string."\n");

View File

@ -0,0 +1,115 @@
<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Form\FormError;
use App\Entity\Config as Entity;
use App\Form\ConfigType as Form;
class ConfigController extends AbstractController
{
private $data = "config";
private $route = "app_config";
private $render = "Config/";
private $entity = "App:Config";
public function list()
{
$em = $this->getDoctrine()->getManager();
$datas = $em->getRepository($this->entity)->findBy(["visible"=>true]);
return $this->render($this->render.'list.html.twig',[
$this->data."s" => $datas,
"useheader" => true,
"usesidebar" => true,
]);
}
public function listrender($category)
{
$em = $this->getDoctrine()->getManager();
$datas = $em->getRepository($this->entity)->findBy(["visible"=>true,"category"=>$category]);
return $this->render($this->render.'render.html.twig',[
$this->data."s" => $datas,
"useheader" => true,
"usesidebar" => true,
]);
}
public function update($id,Request $request)
{
// Initialisation de l'enregistrement
$em = $this->getDoctrine()->getManager();
$data=$em->getRepository($this->entity)->find($id);
if(!$data->getValue())
$data->setValue($this->get('session')->get($data->getId()));
// Création du formulaire
$form = $this->createForm(Form::class,$data,array("mode"=>"update","id"=>$data->getId(),"type"=>$data->getType(),"required"=>$data->getRequired()));
// Récupération des data du formulaire
$form->handleRequest($request);
// Sur erreur
$this->getErrorForm($id,$form,$request,$data,"update");
// Sur validation
if ($form->get('submit')->isClicked() && $form->isValid()) {
$data = $form->getData();
$em->persist($data);
$em->flush();
// Retour à la liste
return $this->redirectToRoute($this->route);
}
// Affichage du formulaire
return $this->render($this->render.'edit.html.twig', [
'useheader' => true,
'usesidebar' => true,
$this->data => $data,
'mode' => 'update',
'form' => $form->createView()
]);
}
public function delete($id,Request $request)
{
// Récupération de l'enregistrement courant
$em = $this->getDoctrine()->getManager();
$config=$em->getRepository($this->entity)->find($id);
if(!$config->getRequired()) {
$config->setValue("");
$em = $this->getDoctrine()->getManager();
$em->persist($config);
$em->flush();
}
return $this->redirectToRoute('app_config');
}
public function logo()
{
return $this->render($this->render.'logo.html.twig');
}
protected function getErrorForm($id,$form,$request,$data) {
if ($form->get('submit')->isClicked() && !$form->isValid()) {
$this->get('session')->getFlashBag()->clear();
$validator = $this->get('validator');
$errors = $validator->validate($data);
foreach( $errors as $error ) {
$request->getSession()->getFlashBag()->add("error", $error->getMessage());
}
$errors = $form->getErrors();
foreach( $errors as $error ) {
$request->getSession()->getFlashBag()->add("error", $error->getMessage());
}
}
}
}

View File

@ -4,48 +4,81 @@ namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
use Symfony\Component\Filesystem\Filesystem;
class CropController extends AbstractController
{
// Etape 01 - Téléchargement de l'image
public function crop01()
public function crop01($type,$reportinput)
{
return $this->render('Crop/crop01.html.twig',[
'useheader' => false,
'usemenu' => false,
'usesidebar' => false,
'type' => $type,
'reportinput' => $reportinput
]);
}
// Etape 02 - Couper votre l'image
public function crop02(Request $request)
public function crop02($type,$reportinput,Request $request)
{
// Récupération de l'image à cropper
$large_image_location = "uploads/avatar/".$this->get('session')->get('uploadavatar');
$file=$request->query->get('file');
$large_image_location = "uploads/$type/$file";
// Récupérer les tailles de l'image
$width = $this->getWidth($large_image_location);
$height = $this->getHeight($large_image_location);
// Définir le pourcentage de réduction de l'image
$max_height=400000;
$max_width=800;
$scale = $max_height/$height;
if(($width*$scale)>$max_width) {
$scale = $max_width/$width;
// Définir le pourcentage de réduction de l'image
switch ($type) {
case "illustration":
$max_height=0;
$ratio="1:1";
break;
case "avatar":
$max_height=900;
$max_width=900;
$ratio="1:1";
break;
case "hero":
$max_height=1600;
$max_width=1600;
$ratio="16:9";
break;
case "image":
$max_height=1600;
$max_width=1600;
$ratio="1:1";
break;
}
if($max_height>0) {
$scale = $max_height/$height;
if(($width*$scale)>$max_width) {
$scale = $max_width/$width;
}
$this->resizeImage($large_image_location,$width,$height,$scale);
}
$this->resizeImage($large_image_location,$width,$height,$scale);
else $scale=1;
// Construction du formulaire
$submited=false;
$form = $this->createFormBuilder()
->add('submit',SubmitType::class,array("label" => "Valider","attr" => array("class" => "btn btn-success","onclick" => "reportThumb()")))
->add('x',HiddenType::class)
->add('y',HiddenType::class)
->add('w',HiddenType::class)
->add('h',HiddenType::class)
->add('xs',HiddenType::class)
->add('ys',HiddenType::class)
->add('ws',HiddenType::class)
->add('hs',HiddenType::class)
->getForm();
// Récupération des data du formulaire
@ -55,16 +88,20 @@ class CropController extends AbstractController
if ($form->get('submit')->isClicked() && $form->isValid()) {
// Récupération des valeurs du formulaire
$data = $form->getData();
$thumb_image_location = "uploads/avatar/thumb_".$this->get('session')->get('uploadavatar');;
$cropped = $this->resizeThumbnailImage($thumb_image_location, $large_image_location,$data["w"],$data["h"],$data["x"],$data["y"],$scale);
$thumb_image_location = "uploads/$type/thumb_".$file;
$cropped = $this->resizeThumbnailImage($thumb_image_location, $large_image_location,$data["ws"],$data["hs"],$data["xs"],$data["ys"],$scale);
$submited=true;
}
return $this->render('Crop/crop02.html.twig', [
'useheader' => false,
'usemenu' => false,
'usesidebar' => false,
'form' => $form->createView(),
'form' => $form->createView(),
'type' => $type,
'file' => $file,
'ratio' => $ratio,
"reportinput" => $reportinput,
"submited" => $submited
]);
}
@ -77,7 +114,6 @@ class CropController extends AbstractController
// Cacul de la largeur
protected function getWidth($image) {
dump($image);
$size = getimagesize($image);
$width = $size[0];
return $width;
@ -125,6 +161,9 @@ class CropController extends AbstractController
}
protected function resizeThumbnailImage($thumb_image_name, $image, $width, $height, $start_width, $start_height, $scale){
$fs = new Filesystem();
$fs->remove($thumb_image_name);
list($imagewidth, $imageheight, $imageType) = getimagesize($image);
$imageType = image_type_to_mime_type($imageType);

View File

@ -107,6 +107,7 @@ class GroupController extends AbstractController
// Controle avant suppression
$error=false;
if($id<0) $error=true;
if($error)
return $this->redirectToRoute($this->route."_update",["id"=>$id]);
else {

View File

@ -26,7 +26,7 @@ class SecurityController extends AbstractController
{
$auth_mode=$this->getParameter("appAuth");
switch($auth_mode) {
case "MYSQL":
case "SQL":
return $this->loginMYSQL($request,$authenticationUtils);
break;
@ -140,7 +140,7 @@ class SecurityController extends AbstractController
public function logout() {
$auth_mode=$this->getParameter("appAuth");
switch($auth_mode) {
case "MYSQL":
case "SQL":
return $this->logoutMYSQL();
break;

View File

@ -29,6 +29,45 @@ class UserController extends AbstractController
]);
}
public function submit(Request $request)
{
// Uniquement possible si appMasteridentity = SQL
if($this->getParameter("appMasteridentity") != "SQL") return $this->redirectToRoute($this->route);
// Initialisation de l'enregistrement
$em = $this->getDoctrine()->getManager();
$data = new Entity();
$data->setAvatar("noavatar.png");
// Création du formulaire
$form = $this->createForm(Form::class,$data,array("mode"=>"submit","appAuth"=>$this->getParameter("appAuth"),"appMasteridentity"=>$this->getParameter("appMasteridentity")));
// Récupération des data du formulaire
$form->handleRequest($request);
// Sur erreur
$this->getErrorForm(null,$form,$request,$data,"submit");
// Sur validation
if ($form->get('submit')->isClicked() && $form->isValid()) {
$data = $form->getData();
$em->persist($data);
$em->flush();
// Retour à la liste
return $this->redirectToRoute($this->route);
}
// Affichage du formulaire
return $this->render($this->render.'edit.html.twig', [
'useheader' => true,
'usesidebar' => true,
$this->data => $data,
'mode' => 'submit',
'form' => $form->createView()
]);
}
public function update($id,Request $request)
{
// Initialisation de l'enregistrement
@ -37,7 +76,7 @@ class UserController extends AbstractController
$oldpassword=$data->getPassword();
// Création du formulaire
$form = $this->createForm(Form::class,$data,array("mode"=>"update","appAuth"=>$this->getParameter("appAuth")));
$form = $this->createForm(Form::class,$data,array("mode"=>"update","appAuth"=>$this->getParameter("appAuth"),"appMasteridentity"=>$this->getParameter("appMasteridentity")));
// Récupération des data du formulaire
$form->handleRequest($request);
@ -71,6 +110,30 @@ class UserController extends AbstractController
]);
}
public function delete($id,Request $request)
{
// Uniquement possible si appMasteridentity = SQL
if($this->getParameter("appMasteridentity") != "SQL") return $this->redirectToRoute($this->route);
// Initialisation de l'enregistrement
$em = $this->getDoctrine()->getManager();
$data=$em->getRepository($this->entity)->find($id);
// Controle avant suppression
$error=false;
if($id<0) $error=true;
if($error)
return $this->redirectToRoute($this->route."_update",["id"=>$id]);
else {
$em->remove($data);
$em->flush();
// Retour à la liste
return $this->redirectToRoute($this->route);
}
}
public function profil(Request $request)
{
// Initialisation de l'enregistrement
@ -79,7 +142,7 @@ class UserController extends AbstractController
$oldpassword=$data->getPassword();
// Création du formulaire
$form = $this->createForm(Form::class,$data,array("mode"=>"profil","appAuth"=>$this->getParameter("appAuth")));
$form = $this->createForm(Form::class,$data,array("mode"=>"profil","appAuth"=>$this->getParameter("appAuth"),"appMasteridentity"=>$this->getParameter("appMasteridentity")));
// Récupération des data du formulaire
$form->handleRequest($request);

View File

@ -0,0 +1,202 @@
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Cron
*
* @ORM\Table(name="config")
* @ORM\Entity(repositoryClass="App\Repository\ConfigRepository")
*/
class Config
{ /**
* @ORM\Id
* @ORM\Column(type="string")
*/
protected $id;
/**
* @ORM\Column(type="string", length=250)
*/
protected $title;
/**
* @ORM\Column(type="text")
*/
protected $value;
/**
* @ORM\Column(name="roworder", type="string")
*/
protected $order;
/**
* @ORM\Column(type="boolean")
*/
protected $visible;
/**
* @ORM\Column(type="boolean")
*/
protected $changeable;
/**
* @ORM\Column(type="boolean")
*/
protected $required;
/**
* @ORM\Column(type="string")
*/
protected $type;
/**
* @ORM\Column(type="string")
*/
protected $grouped;
/**
* @ORM\Column(type="string")
*/
protected $category;
/**
* @ORM\Column(type="text")
*/
protected $help;
public function getId(): ?string
{
return $this->id;
}
public function setId(string $id): self
{
$this->id = $id;
return $this;
}
public function getValue(): ?string
{
return $this->value;
}
public function setValue(string $value): self
{
$this->value = $value;
return $this;
}
public function getOrder(): ?string
{
return $this->order;
}
public function setOrder(string $order): self
{
$this->order = $order;
return $this;
}
public function getVisible(): ?bool
{
return $this->visible;
}
public function setVisible(bool $visible): self
{
$this->visible = $visible;
return $this;
}
public function getChangeable(): ?bool
{
return $this->changeable;
}
public function setChangeable(bool $changeable): self
{
$this->changeable = $changeable;
return $this;
}
public function getRequired(): ?bool
{
return $this->required;
}
public function setRequired(bool $required): self
{
$this->required = $required;
return $this;
}
public function getType(): ?string
{
return $this->type;
}
public function setType(string $type): self
{
$this->type = $type;
return $this;
}
public function getGrouped(): ?string
{
return $this->grouped;
}
public function setGrouped(string $grouped): self
{
$this->grouped = $grouped;
return $this;
}
public function getCategory(): ?string
{
return $this->category;
}
public function setCategory(string $category): self
{
$this->category = $category;
return $this;
}
public function getHelp(): ?string
{
return $this->help;
}
public function setHelp(string $help): self
{
$this->help = $help;
return $this;
}
public function getTitle(): ?string
{
return $this->title;
}
public function setTitle(string $title): self
{
$this->title = $title;
return $this;
}
}

View File

@ -0,0 +1,165 @@
<?php
namespace App\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
use FOS\CKEditorBundle\Form\Type\CKEditorType;
class ConfigType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('submit',
SubmitType::class,
array("label" => "Valider",
"attr" => array("class" => "btn btn-success")));
$builder->add('id',
TextType::class,
array("label" =>"Clé",
"label_attr" => array("style" => 'margin-top:15px;'),
"attr" => array("class" => "form-control"),
'disabled' => true));
switch($options["type"]) {
case "string":
$builder->add('value',
TextType::class,
array("label" => "Valeur",
"label_attr" => array("style" => 'margin-top:15px;'),
"attr" => array("class" => "form-control"),
'required' => ($options["required"]==0?false:true)));
break;
case "boolean":
$choices=["oui" => "1","non" => "0"];
$builder->add("value", ChoiceType::class,
array("label" =>"Valeur",
"label_attr" => array("style" => 'margin-top:15px;'),
"attr" => array("class" => "form-control"),
'required' => ($options["required"]==0?false:true),
"choices" => $choices));
break;
case "integer":
$builder->add("value",
IntegerType::class, [
"label" =>"Valeur",
"label_attr" => array("style" => 'margin-top:15px;'),
"attr" => array("class" => "form-control","min" => "0"),
"required" => ($options["required"]==0?false:true),
]
);
break;
case "pourcentage":
$builder->add("value",
IntegerType::class, [
"label" =>"Valeur",
"label_attr" => array("style" => 'margin-top:15px;'),
"attr" => array("class" => "form-control","min" => "0", "max"=>"100"),
"required" => ($options["required"]==0?false:true),
]
);
break;
case "font":
$choices=[
"ABeeZee-Regular" => "ABeeZee-Regular",
"Acme-Regular" => "Acme-Regular",
"AlfaSlabOne-Regular" => "AlfaSlabOne-Regular",
"Anton-Regular" => "Anton-Regular",
"Baloo-Regular" => "Baloo-Regular",
"CarterOne-Regular" => "CarterOne-Regular",
"Chewy-Regular" => "Chewy-Regular",
"Courgette-Regular" => "Courgette-Regular",
"FredokaOne-Regular" => "FredokaOne-Regular",
"Grandstander" => "Grandstander",
"Helvetica" => "Helvetica",
"Justanotherhand-Regular" => "Justanotherhand-Regular",
"Lato-Regular" => "Lato-Regular",
"LexendDeca-Regular" => "LexendDeca-Regular",
"LuckiestGuy-Regular" => "LuckiestGuy-Regular",
"Overpass-Black" => "Overpass-Black",
"PassionOne" => "PassionOne",
"Peacesans" => "Peacesans",
"Redressed" => "Redressed",
"Righteous-Regular" => "Righteous-Regular",
"Roboto-Regular" => "Roboto-Regular",
"RubikMonoOne-Regular" => "RubikMonoOne-Regular",
"SigmarOne-Regular" => "SigmarOne-Regular",
"Signika-Regular" => "Signika-Regular",
"Teko-Bold" => "Teko-Bold",
"Viga-Regular" => "Viga-Regular",
];
$builder->add("value", ChoiceType::class,
array("label" =>"Valeur",
"label_attr" => array("style" => 'margin-top:15px;'),
"attr" => array("class" => "form-control"),
'required' => ($options["required"]==0?false:true),
"choices" => $choices));
break;
case "editor":
$builder->add('value',
CKEditorType::class,[
"required" => ($options["required"]==0?false:true),
"config" => [
'uiColor' => '#ffffff',
'height' => 600,
'filebrowserUploadRoute' => 'app_ckeditor_upload',
'language' => 'fr',
]
]
);
break;
case "logo":
$builder->add('value',HiddenType::class);
break;
case "hero":
$builder->add('value',HiddenType::class);
break;
case "image":
$builder->add('value',HiddenType::class);
break;
case "color":
$builder->add('value',
TextType::class,
array("label" => "Valeur",
"label_attr" => array("style" => 'margin-top:15px;'),
"attr" => array("class" => "pick-a-color form-control"),
'required' => ($options["required"]==0?false:true)));
break;
}
$builder->add('help',
TextareaType::class,
array("label" =>"Aide",
"attr" => array("class" => "form-control", "style" => "margin-top:15px; height: 200px;"),
'required' => false,
'disabled' => true));
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'App\Entity\Config',
'mode' => "string",
'id' => "string",
'type' => "string",
'required' => "string",
));
}
}

View File

@ -37,7 +37,7 @@ class UserType extends AbstractType
$builder->add('username',
TextType::class, [
"label" =>"Login",
"disabled" => true,
"disabled" => ($options["appMasteridentity"]!="SQL"||$options["mode"]!="submit"),
"attr" => ["autocomplete" => "off"],
]
);
@ -82,7 +82,7 @@ class UserType extends AbstractType
$builder->add('lastname',
TextType::class, [
"label" =>"Nom",
"disabled" => true,
"disabled" => ($options["appMasteridentity"]!="SQL"),
]
);
@ -90,13 +90,13 @@ class UserType extends AbstractType
TextType::class, [
"label" =>"Prénom",
"required" => false,
"disabled" => true, ]
"disabled" => ($options["appMasteridentity"]!="SQL"), ]
);
$builder->add('email',
EmailType::class, [
"label" =>"Email",
"disabled" => true,
"disabled" => ($options["appMasteridentity"]!="SQL"),
]
);
@ -107,14 +107,26 @@ class UserType extends AbstractType
]
);
if($options["appMasteridentity"]=="SQL") {
$builder->add('password',
RepeatedType::class, [
"type" => PasswordType::class,
"required" => ($options["mode"]=="submit"?true:false),
"options" => array("always_empty" => true),
"first_options" => array("label" => "Mot de Passe","attr" => array("class" => "form-control", "style" => "margin-bottom:15px", "autocomplete" => "new-password")),
"second_options" => array('label' => 'Confirmer Mot de Passe',"attr" => array("class" => "form-control", "style" => "margin-bottom:15px"))
]
);
}
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'App\Entity\User',
'mode' => 'string',
'appAuth' => 'string',
'data_class' => 'App\Entity\User',
'mode' => 'string',
'appAuth' => 'string',
'appMasteridentity' => 'string',
));
}
}

View File

@ -0,0 +1,15 @@
<?php
namespace App\Repository;
use App\Entity\Config;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Common\Persistence\ManagerRegistry;
class ConfigRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Config::class);
}
}

View File

@ -0,0 +1,73 @@
<?php
namespace App\Service;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpFoundation\Session\Session;
use Doctrine\ORM\EntityManager;
class sessionInit {
private $container;
protected $em;
protected $session;
public function __construct(ContainerInterface $container, EntityManager $em,Session $session)
{
$this->container = $container;
$this->session = $session;
$this->em = $em;
}
public function onDomainParse(RequestEvent $event) {
$configs = $this->em->getRepository("App:Config")->findAll();
foreach($configs as $config) {
$this->session->set($config->getId(), strval($config->getValue()));
}
// Valeur par défaut appname
if($this->session->get("appname")=="")
$this->session->set("appname", $this->container->getParameter('appName'));
// Valeur par defaut colorbgbodydark = #343a40
if($this->session->get("colorbgbodydark")=="")
$this->session->set("colorbgbodydark", '#343a40');
// Valeur par defaut colorbgbodydark = #ffffff
if($this->session->get("colorbgbodylight")=="")
$this->session->set("colorbgbodylight", '#ffffff');
// Valeur par defaut colorfttitledark = #ffffff
if($this->session->get("colorfttitledark")=="")
$this->session->set("colorfttitledark", '#ffffff');
// Valeur par defaut colorfttitlelight = #343a40
if($this->session->get("colorfttitlelight")=="")
$this->session->set("colorfttitlelight", '#343a40');
// Valeur par defaut colorftbodydark = #ffffff
if($this->session->get("colorftbodydark")=="")
$this->session->set("colorftbodydark", '#ffffff');
// Valeur par defaut colorftbodylight = #343a40
if($this->session->get("colorftbodylight")=="")
$this->session->set("colorftbodylight", '#343a40');
// Valeur par defaut fonttitle = FredokaOne-Regular
if($this->session->get("fonttitle")=="")
$this->session->set("fonttitle", 'FredokaOne-Regular');
// Valeur par defaut fontbody = Roboto-Regular
if($this->session->get("fontbody")=="")
$this->session->set("fontbody", 'Roboto-Regular');
// Valeur par defaut logo
if($this->session->get("logodark")==""&&$this->session->get("logolight")=="") {
$this->session->set("logodark", "logo.png");
$this->session->set("logolight", "logo.png");
}
elseif($this->session->get("logodark")=="")
$this->session->set("logodark", $this->session->get("logolight"));
elseif($this->session->get("logolight")=="")
$this->session->set("logolight", $this->session->get("logodark"));
}
}

View File

@ -88,139 +88,12 @@ class uploadListener
$type=$event->getType();
switch($type) {
case "avatar":
default:
$file=$event->getFile();
$filename=$file->getFilename();
$this->session->set('uploadavatar', $filename);
break;
case "document":
// Récupérer la requete
$request = $event->getRequest();
$nameentity = $request->get('nameentity');
$identity = $request->get('identity');
$directory=$nameentity."/".$identity;
// Recherche de l'entité lié
switch($nameentity) {
case "activity":
$entity=$this->em->getRepository("App:Activity")->find($identity);
break;
case "corrected":
$entity=$this->em->getRepository("App:Activity")->find($identity);
break;
case "answer":
$entity=$this->em->getRepository("App:Answer")->find($identity);
break;
case "answercorrected":
$entity=$this->em->getRepository("App:Answer")->find($identity);
break;
}
// Uniquement si lié à une entité
if(!$entity)
return false;
// Information sur le fichier téléchargé
$file=$event->getFile();
$filename=$file->getFilename();
$pathname=$file->getPath();
$minetype=$file->GetMimeType();
$extention=strtolower($file->GetExtension());
// Déplacer le fichier dans la cible
$fs = new Filesystem();
$fgexit=$fs->exists($pathname."/".$directory."/".$filename);
$file->move($pathname."/".$directory, $filename);
$havethumb=false;
// Création d'un thumb dans le cas d'un fichier de type image
if (in_array(strtolower($file->GetExtension()), array('jpg', 'jpeg', 'jpe', 'png', 'gif', 'bmp'))) {
$fs = new Filesystem();
$fs->copy($pathname."/".$directory."/".$filename,$pathname."/".$directory."/thumb/".$filename);
$max_width=350;
$width = $this->getWidth($pathname."/".$directory."/thumb/".$filename);
$height = $this->getHeight($pathname."/".$directory."/thumb/".$filename);
$scale = $max_width/$width;
$this->resizeImage($pathname."/".$directory."/thumb/".$filename,$width,$height,$scale);
$havethumb=true;
}
// Création d'un thumb dans le cas d'un fichier de type pdf
/*
if (in_array(strtolower($file->GetExtension()), array('pdf'))) {
$im = new \Imagick();
$im->setResolution(350, 350);
$im->readImage($pathname."/".$directory."/".$filename."[0]");
$im->setImageBackgroundColor('#ffffff');
$im = $im->flattenImages();
$im->setImageFormat('jpeg');
$fs->mkdir($pathname."/".$directory."/thumb");
$im->writeImage($pathname."/".$directory."/thumb/".$filename.".jpg");
$fs->rename($pathname."/".$directory."/thumb/".$filename.".jpg", $pathname."/".$directory."/thumb/".$filename);
$havethumb=true;
}
*/
// Creation du document si non existant
switch($nameentity) {
case "activity":
$document=$this->em->getRepository("App:Document")->findBy(["entity"=>$nameentity,"activity"=>$entity,"filename"=>$filename]);
if(!$document) {
$document=new \App\Entity\Document();
$document->setName($filename);
$document->setRoworder(99999);
$document->setFilename($filename);
$document->setActivity($entity);
}
break;
case "corrected":
$document=$this->em->getRepository("App:Document")->findBy(["entity"=>$nameentity,"corrected"=>$entity,"filename"=>$filename]);
if(!$document) {
$document=new \App\Entity\Document();
$document->setName($filename);
$document->setRoworder(99999);
$document->setFilename($filename);
$document->setCorrected($entity);
}
break;
case "answer":
$document=$this->em->getRepository("App:Document")->findBy(["entity"=>$nameentity,"answer"=>$entity,"filename"=>$filename]);
if(!$document) {
$document=new \App\Entity\Document();
$document->setName($filename);
$document->setRoworder(99999);
$document->setFilename($filename);
$document->setAnswer($entity);
}
break;
case "answercorrected":
$document=$this->em->getRepository("App:Document")->findBy(["entity"=>$nameentity,"answercorrected"=>$entity,"filename"=>$filename]);
if(!$document) {
$document=new \App\Entity\Document();
$document->setName($filename);
$document->setRoworder(99999);
$document->setFilename($filename);
$document->setAnswercorrected($entity);
}
break;
}
// Modification du document
$document->setExtention($extention);
$document->setMinetype($minetype);
$document->setHavethumb($havethumb);
$document->setEntity($nameentity);
// Sauvegarde
$this->em->persist($document);
$this->em->flush();
// Retour OK
$response = $event->getResponse();
$response['file'] = $filename;
break;
break;
}
}
}

View File

@ -0,0 +1,94 @@
{% extends 'base.html.twig' %}
{% block body %}
{{ form_start(form) }}
<h1 class="page-header">
{% if mode=="update" %}
Modification CONFIGURATION
{% elseif mode=="submit" %}
Création CONFIGURATION
{% endif %}
</h1>
{{ form_widget(form.submit) }}
<a class="btn btn-secondary" href={{ path('app_config') }}>Annuler</a>
{% if mode=="update" and not config.required %}
<a href="{{ path('app_config_delete',{'id':config.id}) }}"
class="btn btn-danger float-right"
data-method="delete"
data-confirm="Êtes-vous sûr de vouloir supprimer cet entregistrement ?">
Supprimer
</a>
{% endif %}
<br><br>
{% 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">
<div class="card-header">
<i class="fa fa-pencil-alt fa-fw"></i> Informations
</div>
<div class="card-body">
{{ form_row(form.id) }}
{{ form_row(form.value) }}
{% if config.type=="logo" %}
<div style="width:90px; margin:10px auto;">
{% set color = "" %}
{% if config.id=='logodark' %}
{% set color = app.session.get('colorbgbodydark') %}
{% elseif config.id=='logolight' %}
{% set color = app.session.get('colorbgbodylight') %}
{% endif %}
<img id="config_value_img" src="/{{ appAlias }}/uploads/logo/{{ config.value }}" style="background-color: {{color}}; width:90px;height:90px; margin:auto;display:block;">
<a class="btn btn-info" style="width:90px" onClick="ModalLoad('mymodallarge','Logo','{{ path('app_config_logo') }}');" title='Ajouter un Logo'>Modifier</a>
</div>
{% elseif config.type=="hero" %}
<div style="margin:10px auto;">
<img id="config_value_img" src="/{{ appAlias }}/uploads/hero/{{ config.value }}" style="width:100%;margin:auto;display:block;">
<a class="btn btn-info" style="width:100%" onClick="ModalLoad('mymodallarge','Carrousel','{{ path('app_crop01', {"type": "hero", "reportinput": "config_value" }) }}');" title='Ajouter une Bannière'>Modifier</a>
</div>
{% elseif config.type=="image" %}
<div style="margin:10px auto;">
<img id="config_value_img" src="/{{ appAlias }}/uploads/hero/{{ config.value }}" style="width:100%;margin:auto;display:block;">
<a class="btn btn-info" style="width:100%" onClick="ModalLoad('mymodallarge','Image','{{ path('app_crop01', {"type": "image", "reportinput": "config_value" }) }}');" title='Ajouter une Image'>Modifier</a>
</div>
{% endif %}
{{ form_row(form.help) }}
</div>
</div>
{{ form_end(form) }}
{% endblock %}
{% block localjavascript %}
$("#config_value_img").on('error', function(){
var imgSrc = $(this).attr('src');
if(imgSrc!="/{{appAlias}}/uploads/{{config.type}}/")
$(this).attr('src',imgSrc);
});
$('#mymodallarge').on('hidden.bs.modal', function () {
var imgSrc = $("#config_value_img").attr('src');
$("#config_value_img").attr('src',imgSrc);
});
{% endblock %}

View File

@ -0,0 +1,60 @@
{% extends "base.html.twig" %}
{% block body %}
<h1 class="page-header">
CONFIGURATIONS
</h1>
<div class="row mt-4">
<div class="col-md-12">
<h3>Générale</h3>
{{ render(path("app_config_render",{category:"site"})) }}
</div>
<div class="col-md-6">
<h3>Couleurs des fonds de page</h3>
{{ render(path("app_config_render",{category:"colorbgbody"})) }}
</div>
<div class="col-md-6">
<h3>Polices</h3>
{{ render(path("app_config_render",{category:"font"})) }}
</div>
<div class="col-md-6">
<h3>Couleurs des titres </h3>
{{ render(path("app_config_render",{category:"colorfttitle"})) }}
</div>
<div class="col-md-6">
<h3>Couleurs de la police </h3>
{{ render(path("app_config_render",{category:"colorftbody"})) }}
</div>
<div class="col-md-6">
<h3>Logo</h3>
{{ render(path("app_config_render",{category:"logo"})) }}
</div>
</div>
{% endblock %}
{% block localjavascript %}
$(document).ready(function() {
$('#dataTables').DataTable({
columnDefs: [ { "targets": "no-sort", "orderable": false }, { "targets": "no-string", "type" : "num" } ],
responsive: true,
iDisplayLength: 100,
order: [[ 1, "asc" ]]
});
});
{% endblock %}

View File

@ -0,0 +1,42 @@
{% extends "base.html.twig" %}
{% block encorelinktags %}
{{ encore_entry_link_tags('dropzone') }}
{% endblock encorelinktags %}
{% block body %}
<h3 class="page-header">Téléchargez votre Logo</h3>
<a class="btn btn-default" onClick="closeModal();">Annuler</a>
<form action="{{ oneup_uploader_endpoint('logo') }}" class="dropzone" id="MyDropZone" style="margin-top:10px">
</form>
{% endblock %}
{% block encorescripttags %}
{{ encore_entry_script_tags('dropzone') }}
{% endblock %}
{% block localjavascript %}
Dropzone.options.MyDropZone = {
acceptedMimeTypes: 'image/*',
maxFiles: 1,
resizeWidth:500,
success: function( file, response ){
parent.$("#config_value").val(response["file"]);
parent.$("#config_value_img").attr("src","/{{ appAlias }}/uploads/logo/"+response["file"]);
closeModal();
}
}
function closeModal() {
window.parent.$("#mymodallarge").modal('hide');
}
$(window).load(function () {
// On vérifie que l'execution se fait bien dans le cadre d'une modal
if(!window.parent.$("#mymodallarge #framemodal").length) {
$(location).attr('href',"{{ path('app_home') }}");
}
});
{% endblock %}

View File

@ -0,0 +1,78 @@
<table class="table table-striped table-bordered table-hover" id="" style="width:100%">
<tbody>
{% for config in configs|sort((a, b) => a.order <=> b.order) %}
{% set continue = true %}
{% if not config.grouped is empty %}
{% if app.session.get(config.grouped)==0 %}
{% set continue = false %}
{% endif %}
{% endif %}
{%if continue %}
<tr>
<td width="70px">
{% if config.changeable %}
<a href="{{path("app_config_update",{id:config.id})}}"><i class="fa fa-file"></i></a>
{% endif %}
{% if not config.required %}
<a href="{{path("app_config_delete",{id:config.id})}}"><i class="fa fa-trash"></i></a>
{% endif %}
</td>
<td width="50%">{{config.title}}</td>
{% set val = config.value %}
{% if val is empty %}
{% set val=app.session.get(config.id) %}
{% endif %}
{% set color = "" %}
{% set bgcolor = "" %}
{% set otherstyle = "" %}
{% if config.id=='colorbgbodydark' %}
{% set bgcolor = val %}
{% set color = app.session.get('colorfttitledark') %}
{% elseif config.id=='colorbgbodylight' %}
{% set bgcolor = val %}
{% set color = app.session.get('colorfttitlelight') %}
{% elseif config.id=='colorfttitledark' %}
{% set bgcolor = app.session.get('colorbgbodydark') %}
{% set color = val %}
{% elseif config.id=='colorfttitlelight' %}
{% set bgcolor = app.session.get('colorbgbodylight') %}
{% set color = val %}
{% elseif config.id=='colorftbodydark' %}
{% set bgcolor = app.session.get('colorbgbodydark') %}
{% set color = val %}
{% elseif config.id=='colorftbodylight' %}
{% set bgcolor = app.session.get('colorbgbodylight') %}
{% set color = val %}
{% elseif config.id=='logodark' %}
{% set bgcolor = app.session.get('colorbgbodydark') %}
{% set otherstyle = "text-align: center;" %}
{% elseif config.id=='logolight' %}
{% set bgcolor = app.session.get('colorbgbodylight') %}
{% set otherstyle = "text-align: center;" %}
{% endif %}
<td style="overflow-wrap: anywhere; background-color: {{ bgcolor }}; color: {{color}}; {{otherstyle}}" >
{% if config.type=="boolean" %}
{% if val=="0" %} Non
{% elseif val=="1" %} Oui
{%endif%}
{% elseif config.type=="logo" %}
{%if not val is empty %}
<img src="/{{appAlias}}/uploads/logo/{{ val }}" height=50px>
{% endif %}
{% else %}
{{ val|raw }}
{% endif %}
</td>
</tr>
{% endif %}
{% endfor %}
</tbody>
</table>

View File

@ -9,7 +9,7 @@
<h3 class="page-header"></h3>
<button class="btn btn-secondary" onClick="closeModal();">Annuler</button>
<form action="{{ oneup_uploader_endpoint('avatar') }}" class="dropzone" id="MyDropZone" style="margin-top:10px">
<form action="{{ oneup_uploader_endpoint(type) }}" class="dropzone" id="MyDropZone" style="margin-top:10px">
{% endblock %}
@ -26,11 +26,11 @@
acceptedMimeTypes: 'image/*',
//renameFilename: false,
success: function(file, response){
$(location).attr('href',"{{ path('app_crop02') }}");
$(location).attr('href',"{{ path('app_crop02', {"type": type, "reportinput": reportinput }) }}?file="+response["file"]);
}
}
function closeModal() {
window.parent.$("#extraLargeModal").modal('hide');
window.parent.$("#mymodallarge").modal('hide');
}
{% endblock %}

View File

@ -1,41 +1,64 @@
{% extends 'base.html.twig' %}
{% block localstyle %}
img.crop-image{ width:100% }
{% endblock %}
{% block body %}
{{ form_start(form) }}
{{ form_widget(form.submit) }}
<button class="btn btn-secondary" onClick="closeModal();">Annuler</button>
<div id='preview' style='overflow:hidden; width:90px; height:90px; position: absolute; top: 0px; right: 10px;'>
<img src="/{{ appAlias }}/uploads/avatar/{{ app.session.get('uploadavatar') }}" style='position: relative;' alt='Thumbnail Preview' />
{% if ratio=="1:1" %}
{% set class="width:90px; height:90px;" %}
{% elseif ratio=="16:9" %}
{% set class="width:160px; height:90px;" %}
{% elseif ratio=="16:2" %}
{% set class="width:160px; height:20px;" %}
{% endif %}
<div id='preview' style='overflow:hidden; {{class}} position: absolute; top: 0px; right: 10px;'>
<img src="/{{ appAlias }}/uploads/{{type}}/{{ file }}" style='position: relative;' alt='Thumbnail Preview' />
</div>
<div style="width:800px; height:590px; overflow:hidden; margin:65px auto 0px auto;">
<div id="largeimg" class="crop-select-js" style="width:800px;">
<div style="width:100%; margin:65px auto 0px auto;">
<div id="largeimg" style="width:800px;margin:auto;">
</div>
</div>
{{ form_end(form) }}
{% endblock %}
{% block localjavascript %}
function move(data) {
$('#form_x').val(data.xScaledToImage);
$('#form_y').val(data.yScaledToImage);
$('#form_x').val(data.x);
$('#form_y').val(data.y);
$('#form_xs').val(data.xScaledToImage);
$('#form_ys').val(data.yScaledToImage);
preview();
}
function resize(data) {
$('#form_w').val(data.widthScaledToImage);
$('#form_h').val(data.heightScaledToImage);
$('#form_w').val(data.width);
$('#form_h').val(data.height);
$('#form_ws').val(data.widthScaledToImage);
$('#form_hs').val(data.heightScaledToImage);
preview();
}
function preview(data) {
var scaleX = 90 / $('#form_w').val();
var scaleY = 90 / $('#form_h').val();
{% if ratio=="1:1" %}
var scaleX = 90 / $('#form_w').val();
var scaleY = 90 / $('#form_h').val();
{% elseif ratio=="16:9" %}
var scaleX = 160 / $('#form_w').val();
var scaleY = 160 / $('#form_h').val();
{% elseif ratio=="16:2" %}
var scaleX = 160 / $('#form_w').val();
var scaleY = 160 / $('#form_h').val();
{% endif %}
$('#preview img').css({
width: Math.round(scaleX * $('#largeimg').width()) + 'px',
@ -47,24 +70,47 @@
}
function reportThumb() {
window.parent.$("#user_avatar").val("thumb_{{ app.session.get('uploadavatar') }}");
window.parent.$("#user_avatar_img").attr("src","/{{ appAlias }}/uploads/avatar/thumb_{{ app.session.get('uploadavatar') }}");
closeModal();
{% if reportinput == "refresh" %}
window.parent.location.reload();
{% elseif reportinput != "none" %}
window.parent.$("#{{ reportinput }}").val("thumb_{{ file }}");
window.parent.$("#{{ reportinput }}_img").attr("src","/{{ appAlias }}/uploads/{{ type }}/thumb_{{ file }}");
{% endif %}
closeModal();
}
function closeModal() {
window.parent.$("#extraLargeModal").modal('hide');
window.parent.$("#mymodallarge").modal('hide');
}
$(document).ready(function() {
window.parent.$(".modal-title").html("ETAPE 2 - Découper votre image");
realheight=$('#largeimg').height();
realwidth=$('#largeimg').width();
if(realheight>505) { $('#largeimg').height(505); $('#largeimg').width("auto") }
if($('#largeimg').width() > 868) { $('#largeimg').width(868); $('#largeimg').height("auto") }
resizeheight=$('#largeimg').height();
resizewidth=$('#largeimg').width();
$('#largeimg').CropSelectJs({
imageSrc: "/{{ appAlias }}/uploads/avatar/{{ app.session.get('uploadavatar') }}",
imageSrc: "/{{ appAlias }}/uploads/{{type}}/{{ file }}",
selectionResize: function(data) { resize(data); },
selectionMove: function(data) { move(data); },
});
$('#largeimg').CropSelectJs('setSelectionAspectRatio',1);
{% if ratio=="1:1" %}
{% set nbratio=1 %}
{% elseif ratio=="16:9" %}
{% set nbratio=(16/9) %}
{% elseif nbratio=="16:2" %}
{% set class=(16/2) %}
{% endif %}
$('#largeimg').CropSelectJs('setSelectionAspectRatio',{{nbratio}});
});

View File

@ -1,18 +1,15 @@
{% extends "base.html.twig" %}
{% block localstyle %}
body {
background-color: #efefef;
}
.homecard {
padding-top: 20px;
label {
color: var(--colorftbodylight);
}
{% endblock %}
{% block body %}
<div style="text-align:center">
<img src="/{{appAlias}}/images/logo.png" style="height:120px;margin-top:10px;"><br>
<h1>{{appName}}</h1>
<img src="/{{ appAlias }}/uploads/logo/{{ app.session.get('logodark') }}" style="height:120px;margin-top:10px;">
<h1 style="border:none">{{appName}}</h1>
<form action="{{ path('app_login') }}" method="post">
<div class="card homecard" style="width:400px; margin:auto">
<div class="card-body">
@ -33,4 +30,10 @@
</div>
</form>
</div>
{% endblock %}
{% block localjavascript %}
$(document).ready(function() {
$("#username").focus();
});
{% endblock %}

View File

@ -18,6 +18,6 @@ $(document).ready(function() {
function ModalLoad(idmodal,title,path) {
$("#"+idmodal+" .modal-header h4").text(title);
$("#"+idmodal+" #framemodal").attr("src",path);
$("#"+idmodal+" iframe").attr("src",path);
$("#"+idmodal).modal("show");
}

View File

@ -3,6 +3,13 @@
{% if is_granted('ROLE_ADMIN') %}
<br>
<li class="title">Administration</li>
<li>
<a href="{{path("app_config")}}">
<i class="fa fa-cog"></i>Configurations
</a>
</li>
<li>
<a href="{{path("app_user")}}">
<i class="fa fa-user"></i>Utilisateurs

View File

@ -1,148 +1,108 @@
/* global */
h1{
padding: 40px 0px 9px 0px;
border-bottom: 1px solid #eee;
:root{
--colorbgbodylight: {{ app.session.get('colorbgbodylight')|raw }};
--colorbgbodydark: {{ app.session.get('colorbgbodydark')|raw }};
--colorfttitlelight: {{ app.session.get('colorfttitlelight')|raw }};
--colorfttitledark: {{ app.session.get('colorfttitledark')|raw }};
--colorftbodylight: {{ app.session.get('colorftbodylight')|raw }};
--colorftbodydark: {{ app.session.get('colorftbodydark')|raw }};
--fontbody: "{{ app.session.get('fontbody')|raw }}";
--fonttitle: "{{ app.session.get('fonttitle')|raw }}";
}
.nav a{
background: none;
color: #CFD8DC;
font-size: 14px;
padding: 5px 0px 5px 25px;
display: block;
/* COLOR BODY */
body {
background-color: var(--colorbgbodylight);
color: var(--colorftbodylight);
}
.card {
background-color: var(--colorbgbodylight);
}
body .navbar.bg-dark {
background-color: var(--colorbgbodydark)!important;
}
body #sidebar {
background-color: var(--colorbgbodydark);
}
body #sidebar .title {
color: var(--colorfttitledark);
}
body #sidebar .nav a {
color: var(--colorfttitledark);
}
body h1, body h2, body h3 {
color: var(--colorfttitlelight);
}
body a, body .btn-link {
color: var(--colorfttitlelight);
}
body .nav a{
color: var(--colorfttitledark);
}
/* Sidebar Styles */
.contentsidebar {
margin-left:250px;
/* COLOR BODY HOME */
body.monocolor {
background-color: var(--colorbgbodydark);
color: var(--colorftbodydark);
}
#sidebar {
z-index: 1000;
position: fixed;
left: 250px;
width: 250px;
height: 100%;
margin-left: -250px;
overflow-y: auto;
background: #37474F;
-webkit-transition: all 0.5s ease;
-moz-transition: all 0.5s ease;
-o-transition: all 0.5s ease;
transition: all 0.5s ease;
body.monocolor .card {
background-color: var(--colorbgbodydark);
}
#sidebar header {
background-color: #263238;
font-size: 20px;
line-height: 52px;
text-align: center;
body.monocolor .navbar.bg-dark {
background-color: var(--colorbgbodydark)!important;
}
#sidebar header a {
color: #fff;
display: block;
text-decoration: none;
body.monocolor #sidebar {
background-color: var(--colorbgbodydark);
}
#sidebar header a:hover {
color: #fff;
body.monocolor #sidebar .title {
color: var(--colorfttitledark);
}
#sidebar .nav{
display: block;
body.monocolor #sidebar .nav a {
color: var(--colorfttitledark);
}
#sidebar .nav a {
padding: 0px 10px 5px 10px;
body.monocolor h1, body.monocolor h2, body.monocolor h3 {
color: var(--colorfttitledark);
}
#sidebar .nav .last{
border-bottom: 5px solid #455A64;
padding-bottom:5px;
body.monocolor a, body.monocolor .btn-link {
color: var(--colorfttitledark);
}
#sidebar .title {
color: #CFD8DC;
font-size: 16px;
padding: 0px 10px 0px 10px;
display: block;
text-transform: uppercase;
margin-left: 0px !important;
font-weight: bold;
body.monocolor .nav a{
color: var(--colorfttitledark);
}
#sidebar .nav .last{
border-bottom: 5px solid #455A64;
padding-bottom:5px;
/* FONT */
body {
font-family: var(--fontbody);
}
#sidebar .nav a:hover{
background: none;
color: #ECEFF1;
h1,h2,h3, .navbar-brand {
font-family: var(--fonttitle);
}
#sidebar .nav a .fa{
margin-right: 5px;
}
#sidebar .nav .select-control {
padding: 0px 10px 5px 10px;
margin-top: -12px;
}
.avatar {
background-color: #343a40;
width: 35px;
height: 35px;
border-radius: 100%;
margin-top: -5px;
}
.avatar.big{
width: 90px;
height: 90px;
margin-bottom: 10px;
}
@media (max-width: 991px) {
.contentsidebar {
margin-left: auto;
}
#sidebar {
position: static;
margin:0px -15px;
width: auto;
}
}
a.btn {
color:#ffffff;
}
.btn-link {
{% if not useheader is defined or not useheader %}
#main {
padding:0px;
}
.media-body p {
font-size :12px;
margin-bottom:0px;
}
@media (min-width: 992px) {
#sidebar {
display: block;
}
}
{% if useheader is defined and useheader %}
#main {
padding-top:55px;
}
{% endif %}
th.dt-center, td.dt-center { text-align: center; }
{%endif%}

View File

@ -47,8 +47,8 @@
{% endif %}
<img id="user_avatar_img" src="{{ avatar|urlavatar }}" class="avatar big" >
{{ form_widget(form.avatar) }}
{% if appMasteridentity=="LDAP" %}
<a class="btn btn-info" style="width:100%; margin-bottom:15px;" onClick="showModal();" title='Ajouter un avatar'>Modifier</a>
{% if appMasteridentity=="LDAP" or appMasteridentity=="SQL" %}
<a class="btn btn-info" style="width:100%; margin-bottom:15px;" onClick="ModalLoad('mymodallarge','Avatar','{{ path('app_crop01', {"type": "avatar", "reportinput": "user_avatar" }) }}');" title='Ajouter un avatar'>Modifier</a>
{% endif %}
</div>
@ -89,21 +89,6 @@
</div>
{{ form_end(form) }}
<div id="extraLargeModal" class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog modal-xl">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title"></h5>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
</div>
<div class="modal-body">
<iframe id="frameModal" frameborder=0 width="100%" height="700px"></iframe>
</div>
</div>
</div>
</div>
{% endblock %}
{% block localjavascript %}
@ -121,9 +106,4 @@
if(imgSrc!="/{{appAlias}}/uploads/avatar/")
$(this).attr('src',imgSrc);
});
function showModal() {
$("#frameModal").attr("src","{{path("app_crop01")}}");
$("#extraLargeModal").modal("show");
}
{% endblock %}

View File

@ -5,6 +5,10 @@
UTILISATEURS
</h1>
{% if appMasteridentity == "SQL" %}
<p><a class="btn btn-success" href={{ path('app_user_submit') }}>Ajouter</a></p>
{% endif %}
<div class="card">
<div class="card-header">
<i class="fa fa-table fa-fw"></i> Liste des Utilisateurs
@ -29,6 +33,9 @@ UTILISATEURS
<tr>
<td>
<a href="{{path("app_user_update",{id:user.id})}}"><i class="fa fa-file"></i></a>
{% if user.id >=0 and appMasteridentity == "SQL" %}
<a href="{{path("app_user_delete",{id:user.id})}}" data-method="delete" data-confirm="Êtes-vous sûr de vouloir supprimer cet enregistrement ?"><i class="fa fa-trash"></i></a>
{% endif %}
</td>
<td><img id="user_avatar_img" src="{{ user.avatar|urlavatar }}" class="avatar" ></td>
<td>{{user.username}}</td>

View File

@ -2,7 +2,7 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html"; charset="utf-8" />
<title>{% block title %}{{ appName }}{% endblock %}</title>
<title>{% block title %}{{app.session.get("appname")}}{% endblock %}</title>
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
@ -14,9 +14,11 @@
{% endblock encorelinktags %}
<link type="text/css" rel="stylesheet" href="{{ asset('bundles/craueformflow/css/buttons.css') }}" />
<link rel="shortcut icon" href="/{{ appAlias }}/images/logo.png" />
<link rel="shortcut icon" href="/{{ appAlias }}/uploads/logo/{{app.session.get("logolight")}}" />
</head>
<link href="/{{ appAlias }}/styles/css/font.css" rel="stylesheet" media="screen" />
<link href="/{{ appAlias }}/styles/css/style.css" rel="stylesheet" media="screen" />
<style>
{{ include('Include/style.css.twig') }}
@ -26,12 +28,17 @@
{% endblock %}
</style>
<body>
{% set class="" %}
{% if usemonocolor is defined and usemonocolor %}
{% set class="monocolor" %}
{% endif %}
<body class={{ class }}>
{% if useheader is defined and useheader %}
<nav class="navbar navbar-expand-lg navbar-dark fixed-top bg-dark">
<a class="navbar-brand" href="{{ path('app_home')}}">
<img src="/{{appAlias}}/images/logo.png" style="height:30px;margin-top:-3px;">
{{appName}}
<img src="/{{ appAlias }}/uploads/logo/{{app.session.get("logodark")}}" style="height:30px;margin-top:-3px;">
{{app.session.get("appname")}}
</a>
{% if usesidebar is defined and usesidebar %}
@ -62,13 +69,13 @@
<li>
{% if app.user %}
{% if appAuth=="MYSQL" %}
{% if appAuth=="SQL" %}
<a href="{{path("app_logout")}}"><i class="fa fa-sign-out-alt fa-fw"></i></a>
{% elseif appAuth=="CAS" %}
<a href="{{path("app_logoutcas")}}"><i class="fa fa-sign-out-alt fa-fw"></i></a>
{% endif %}
{% else %}
{% if appAuth=="MYSQL" %}
{% if appAuth=="SQL" %}
<a href="{{path("app_login")}}"><i class="fa fa-sign-in-alt fa-fw"></i></a>
{% elseif appAuth=="CAS" %}
<a href="{{path("app_logincas")}}"><i class="fa fa-sign-in-alt fa-fw"></i></a>
@ -110,6 +117,19 @@
</div>
</div>
<div id="mymodallarge" class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog modal-xl">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title"></h4>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
</div>
<div class="modal-body">
<iframe frameborder=0 width="100%" height="700px"></iframe>
</div>
</div>
</div>
</div>
{{ encore_entry_script_tags('app') }}
@ -126,6 +146,13 @@
</script>
<script>
$(".pick-a-color").spectrum(
{
type: "text",
showAlpha: false
}
);
{% block localjavascript %}
{% endblock %}