Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
mathieu
potage
Commits
3d921b28
Commit
3d921b28
authored
Jun 17, 2018
by
Mat
Browse files
Template de base pour l'entité Lettre
parent
684d7d4c
Changes
12
Hide whitespace changes
Inline
Side-by-side
src/APIBundle/Controller/LettreAPIController.php
View file @
3d921b28
...
...
@@ -3,6 +3,7 @@
namespace
APIBundle\Controller
;
use
APIBundle\Form\LettreAPIType
;
use
APIBundle\Form\LettreStatusAPIType
;
use
PotageBundle\Entity\Lettre
;
use
Symfony\Component\HttpFoundation\Request
;
use
Symfony\Component\HttpFoundation\Response
;
...
...
@@ -10,13 +11,42 @@ use Symfony\Component\HttpFoundation\Response;
class
LettreAPIController
extends
MasterAPIController
{
/**
* @return string
* @throws \Doctrine\ORM\NonUniqueResultException
*/
private
function
newReference
()
{
$now
=
new
\
DateTime
();
$today
=
$now
->
format
(
'ymd'
);
$em
=
$this
->
getDoctrine
()
->
getManager
();
$num
=
$em
->
getRepository
(
'PotageBundle:Lettre'
)
->
findOneLastReference
(
$today
);
if
(
$num
!==
null
)
{
$last
=
intval
(
substr
(
$num
[
'reference'
],
-
2
));
$last
++
;
$last
=
sprintf
(
"%02d"
,
$last
);
}
else
{
$last
=
'01'
;
}
return
'LT'
.
$today
.
$last
;
}
/**
* @param Request $request
* @return \Symfony\Component\HttpFoundation\JsonResponse
* @throws \Doctrine\ORM\NonUniqueResultException
*/
public
function
createAction
(
Request
$request
)
{
$lettre
=
new
Lettre
();
$reference
=
$this
->
newReference
();
$lettre
=
new
Lettre
(
$reference
);
$form
=
$this
->
createForm
(
LettreAPIType
::
class
,
$lettre
);
$form
->
handleRequest
(
$request
);
...
...
@@ -34,12 +64,13 @@ class LettreAPIController extends MasterAPIController
/**
* @param $status
* @return \Symfony\Component\HttpFoundation\JsonResponse
*/
public
function
read
Action
(
)
public
function
read
ByStatusAction
(
$status
)
{
$em
=
$this
->
getDoctrine
()
->
getManager
();
$lettres
=
$em
->
getRepository
(
'PotageBundle:Lettre'
)
->
findAll
ForAPIRead
(
);
$lettres
=
$em
->
getRepository
(
'PotageBundle:Lettre'
)
->
findAll
ByStatusForRead
(
$status
);
return
$this
->
api
(
$lettres
);
}
...
...
@@ -87,6 +118,33 @@ class LettreAPIController extends MasterAPIController
}
/**
* @param Request $request
* @param $id
* @return \Symfony\Component\HttpFoundation\JsonResponse
* @throws \Doctrine\ORM\NonUniqueResultException
*/
public
function
updateStatusAction
(
Request
$request
,
$id
)
{
$em
=
$this
->
getDoctrine
()
->
getManager
();
$lettre
=
$em
->
getRepository
(
'PotageBundle:Lettre'
)
->
findOneForAPIUpdate
(
$id
);
$form
=
$this
->
createForm
(
LettreStatusAPIType
::
class
,
$lettre
);
$form
->
handleRequest
(
$request
);
if
(
$lettre
===
null
)
{
return
$this
->
api
(
'Not found'
,
Response
::
HTTP_NOT_FOUND
);
}
if
(
$form
->
isSubmitted
()
&&
$form
->
isValid
())
{
$em
->
flush
();
return
$this
->
api
(
$lettre
);
}
return
$this
->
api
(
$form
,
Response
::
HTTP_BAD_REQUEST
);
}
/**
* @param $id
* @return \Symfony\Component\HttpFoundation\JsonResponse
...
...
src/APIBundle/Form/LettreStatusAPIType.php
0 → 100755
View file @
3d921b28
<?php
namespace
APIBundle\Form
;
use
PotageBundle\Form\Lettre\LettreStatusType
;
use
Symfony\Component\OptionsResolver\OptionsResolver
;
class
LettreStatusAPIType
extends
LettreStatusType
{
/**
* @param OptionsResolver $resolver
*/
public
function
configureOptions
(
OptionsResolver
$resolver
)
{
parent
::
configureOptions
(
$resolver
);
$resolver
->
setDefault
(
'csrf_protection'
,
false
);
// TODO temporaire, le temps de régler les validations au niveau des Asserts et des FormType
$resolver
->
setDefault
(
'attr'
,
array
(
'novalidate'
=>
true
));
}
}
src/APIBundle/Resources/config/routing.yml
View file @
3d921b28
...
...
@@ -150,10 +150,12 @@ api_offre_legumes_delete:
## CRUD LettreAPI
api_lettre_read
:
path
:
/lettres
api_lettre_read_by_status
:
path
:
/lettres/{status}
requirements
:
status
:
\w+
defaults
:
_controller
:
APIBundle:LettreAPI:read
_controller
:
APIBundle:LettreAPI:read
ByStatus
methods
:
[
GET
]
api_lettre_create
:
...
...
@@ -178,6 +180,14 @@ api_lettre_update:
_controller
:
APIBundle:LettreAPI:update
methods
:
[
POST
]
api_lettre_update_status
:
path
:
/lettre/{id}/status
requirements
:
id
:
\d+
defaults
:
_controller
:
APIBundle:LettreAPI:updateStatus
methods
:
[
POST
]
api_lettre_delete
:
path
:
/lettre/{id}
requirements
:
...
...
src/PotageBundle/Entity/Lettre.php
View file @
3d921b28
...
...
@@ -90,13 +90,15 @@ class Lettre
private
$updatedAt
;
/**
* Lettre constructor.
*
* @param $reference
*/
public
function
__construct
()
public
function
__construct
(
$reference
)
{
$this
->
infos
=
new
ArrayCollection
();
$this
->
reference
=
$reference
;
}
/**
...
...
@@ -353,14 +355,15 @@ class Lettre
return
$this
->
infos
;
}
/**
* Set groupe
*
* @param
integer
$groupe
* @param
\PotageBundle\Entity\Groupe
$groupe
*
* @return Lettre
*/
public
function
setGroupe
(
$groupe
)
public
function
setGroupe
(
\
PotageBundle\Entity\Groupe
$groupe
)
{
$this
->
groupe
=
$groupe
;
...
...
@@ -370,7 +373,7 @@ class Lettre
/**
* Get groupe
*
* @return
integer
* @return
\PotageBundle\Entity\Groupe
*/
public
function
getGroupe
()
{
...
...
src/PotageBundle/Form/Lettre/LettreStatusType.php
0 → 100755
View file @
3d921b28
<?php
namespace
PotageBundle\Form\Lettre
;
use
PotageBundle\Entity\Lettre
;
use
Symfony\Component\Form\AbstractType
;
use
Symfony\Component\Form\Extension\Core\Type\ChoiceType
;
use
Symfony\Component\Form\Extension\Core\Type\SubmitType
;
use
Symfony\Component\Form\FormBuilderInterface
;
use
Symfony\Component\OptionsResolver\OptionsResolver
;
class
LettreStatusType
extends
AbstractType
{
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public
function
buildForm
(
FormBuilderInterface
$builder
,
array
$options
)
{
$builder
->
add
(
'status'
,
ChoiceType
::
class
,
array
(
'label'
=>
'Statut'
,
'choices'
=>
array
(
'En préparation'
=>
'draft'
,
'Envoyer'
=>
'current'
,
),
'label_attr'
=>
array
(
'class'
=>
'col-form-label'
),
'attr'
=>
array
(
'class'
=>
'form-control form-control-sm'
,
),
));
$builder
->
add
(
'sauver'
,
SubmitType
::
class
,
array
(
'label'
=>
'Changer'
,
'attr'
=>
array
(
'class'
=>
'btn btn-dark mb-2'
)
));
}
/**
* @param OptionsResolver $resolver
*/
public
function
configureOptions
(
OptionsResolver
$resolver
)
{
parent
::
configureOptions
(
$resolver
);
$resolver
->
setDefault
(
'data_class'
,
Lettre
::
class
);
$resolver
->
setDefault
(
'attr'
,
array
(
'class'
=>
'formulaire formulaire_offre_status'
,
));
}
/**
* @return null|string
*/
public
function
getBlockPrefix
()
{
return
'offre_status'
;
}
}
src/PotageBundle/Form/Lettre/LettreType.php
View file @
3d921b28
...
...
@@ -51,16 +51,20 @@ class LettreType extends AbstractType
);
// infos
/*
$builder->add('infos', EntityType::class, array(
'class' => Info::class,
'label' => "Dans laquelle on glisse des infos",
'label_attr' => array('class' => 'col-form-label'),
'attr' => array('class' => 'form-control form-control-sm'),
));
*/
// groupe
$builder
->
add
(
'groupe'
,
EntityType
::
class
,
array
(
'class'
=>
Groupe
::
class
,
'choice_label'
=>
'getNom'
,
'placeholder'
=>
''
,
'label'
=>
"À destination d'un groupe"
,
'label_attr'
=>
array
(
'class'
=>
'col-form-label'
),
'attr'
=>
array
(
'class'
=>
'form-control form-control-sm'
),
...
...
src/PotageBundle/Repository/LettreRepository.php
View file @
3d921b28
...
...
@@ -12,12 +12,32 @@ class LettreRepository extends \Doctrine\ORM\EntityRepository
{
/**
* @return array Lettre
* @param $pattern
* @return mixed
* @throws \Doctrine\ORM\NonUniqueResultException
*/
public
function
findOneLastReference
(
$pattern
)
{
$qb
=
$this
->
createQueryBuilder
(
'l'
)
->
select
(
'l.reference'
)
->
where
(
'l.reference LIKE :pattern'
)
->
setParameter
(
':pattern'
,
'%'
.
$pattern
.
'%'
)
->
orderBy
(
'l.reference'
,
'DESC'
)
->
setMaxResults
(
1
);
return
$qb
->
getQuery
()
->
getOneOrNullResult
();
}
/**
* @param $status
* @return array
*/
public
function
findAll
ForAPIRead
(
)
public
function
findAll
ByStatusForRead
(
$status
)
{
$qb
=
$this
->
createQueryBuilder
(
'l'
)
->
orderBy
(
'l.id'
,
'DESC'
);
->
where
(
'l.status = :status'
)
->
setParameter
(
':status'
,
$status
)
->
orderBy
(
'l.status'
)
->
addOrderBy
(
'l.reference'
,
'DESC'
);
return
$qb
->
getQuery
()
->
getResult
();
}
...
...
src/PotageBundle/Resources/views/Lettre/ajaxDisplay.html.twig
View file @
3d921b28
...
...
@@ -8,6 +8,7 @@
<nav
class=
"navbar navbar-expand-lg navbar-light bg-light navbar-search"
>
<a
href=
"
{{
path
(
'potage_offre_ajax_display'
)
}}
"
class=
"nav-laterale left text-secondary"
><i
class=
"fas fa-long-arrow-alt-left fa-fw"
></i>
Les offres
</a>
<a
href=
"
{{
path
(
'potage_groupe_ajax_display'
)
}}
"
class=
"nav-laterale right text-secondary"
>
Les groupes
<i
class=
"fas fa-long-arrow-alt-right fa-fw"
></i></a>
</nav>
{%
endblock
%}
...
...
@@ -79,41 +80,41 @@
<div
class=
"col right hd-1"
>
<div
style=
"margin-top: 0.65em;"
>
{#
#}
<a
href=
"javascript: void(0);"
class=
"btn btn-outline-dark mb-2 btn-sm btn-reload"
>
<i
class=
"fas fa-sync-alt"
></i>
Rafraîchir la liste
</a>
#}
</div>
</div>
</div>
<div
class=
"tab-content"
id=
"v-pills-tabContent"
>
<div
class=
"tab-pane fade show active"
id=
"v-pills-actuel"
role=
"tabpanel"
aria-labelledby=
"v-pills-actuel-tab"
>
<h2><i
class=
"fas fa-angle-down fa-fw"
></i>
En préparation
</h2>
<table
id=
"maintab-draft"
class=
"table
off
res table-striped"
>
<table
id=
"maintab-draft"
class=
"table
lett
res table-striped"
>
<thead>
<tr>
<th
scope=
"col"
>
#
</th>
<th
scope=
"col"
>
Off
re
</th>
<th
scope=
"col"
>
Contenu
</th>
<th
scope=
"col"
>
Créée le
</th>
<th
scope=
"col"
>
Date de clôtur
e
</th>
<th
scope=
"col"
>
Référence
</th>
<th
scope=
"col"
>
Infolett
re
</th>
<th
scope=
"col"
>
Groupe
</th>
<th
scope=
"col"
>
Sujet
</th>
<th
scope=
"col"
>
Pièce joint
e
</th>
<th
scope=
"col"
>
Actions
</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<h2><i
class=
"fas fa-angle-down fa-fw"
></i>
En cours
</h2>
<table
id=
"maintab-current"
class=
"table
off
res table-striped"
>
<h2><i
class=
"fas fa-angle-down fa-fw"
></i>
En cours
d'envoi
</h2>
<table
id=
"maintab-current"
class=
"table
lett
res table-striped"
>
<thead>
<tr>
<th
scope=
"col"
>
#
</th>
<th
scope=
"col"
>
Off
re
</th>
<th
scope=
"col"
>
Contenu
</th>
<th
scope=
"col"
>
Créée le
</th>
<th
scope=
"col"
>
Date de clôtur
e
</th>
<th
scope=
"col"
>
Référence
</th>
<th
scope=
"col"
>
Infolett
re
</th>
<th
scope=
"col"
>
Groupe
</th>
<th
scope=
"col"
>
Sujet
</th>
<th
scope=
"col"
>
Pièce joint
e
</th>
<th
scope=
"col"
>
Actions
</th>
</tr>
</thead>
<tbody>
...
...
@@ -121,16 +122,16 @@
</table>
</div>
<div
class=
"tab-pane fade"
id=
"v-pills-archives"
role=
"tabpanel"
aria-labelledby=
"v-pills-archives-tab"
>
<h2><i
class=
"fas fa-angle-down fa-fw"
></i>
Archiv
es
</h2>
<table
id=
"maintab-closed"
class=
"table
off
res table-striped"
>
<h2><i
class=
"fas fa-angle-down fa-fw"
></i>
Envoyé
es
</h2>
<table
id=
"maintab-closed"
class=
"table
lett
res table-striped"
>
<thead>
<tr>
<th
scope=
"col"
>
#
</th>
<th
scope=
"col"
>
Off
re
</th>
<th
scope=
"col"
>
Contenu
</th>
<th
scope=
"col"
>
Créée le
</th>
<th
scope=
"col"
>
Date de clôtur
e
</th>
<th
scope=
"col"
>
Référence
</th>
<th
scope=
"col"
>
Infolett
re
</th>
<th
scope=
"col"
>
Groupe
</th>
<th
scope=
"col"
>
Sujet
</th>
<th
scope=
"col"
>
Pièce joint
e
</th>
<th
scope=
"col"
>
Actions
</th>
</tr>
</thead>
<tbody>
...
...
@@ -147,5 +148,273 @@
<script
type=
"text/javascript"
src=
"
{{
asset
(
'js/ajax_functions.js'
)
}}
"
></script>
<script
type=
"text/javascript"
>
/*
* Recharge la table Lettre
* chaque table affiche les lettres pour un statut donné
* @param string status
*/
function
reloadTableLettre
(
status
)
{
let
table
=
document
.
querySelector
(
'
table#maintab-
'
+
status
+
'
.lettres
'
);
let
tbody
=
table
.
querySelector
(
'
tbody
'
);
tbody
.
innerHTML
=
null
;
let
lettreURL
=
Routing
.
generate
(
'
api_lettre_read_by_status
'
,
{
'
status
'
:
status
});
AJAX
(
'
GET
'
,
lettreURL
,
function
(
request
)
{
let
json
=
JSON
.
parse
(
request
.
responseText
);
for
(
let
i
=
0
;
i
<
json
.
length
;
i
++
)
{
let
tr
=
buildRowLettre
(
json
[
i
]);
tbody
.
appendChild
(
tr
);
}
});
}
/*
* Construit une rangée du tableau des groupes
*/
function
buildRowLettre
(
jsonRow
)
{
console
.
log
(
jsonRow
);
let
tr
=
document
.
createElement
(
'
tr
'
);
let
td1
=
document
.
createElement
(
'
td
'
);
td1
.
textContent
=
jsonRow
.
id
;
tr
.
appendChild
(
td1
);
let
td7
=
document
.
createElement
(
'
td
'
);
let
listStatus
=
{
'
draft
'
:
'
En préparation
'
,
'
current
'
:
'
Publiée
'
,
'
closed
'
:
'
Terminée
'
};
for
(
let
statut
in
listStatus
)
{
if
(
statut
===
jsonRow
.
status
)
{
if
(
jsonRow
.
status
===
'
draft
'
&&
typeof
jsonRow
.
offre
!==
'
undefined
'
)
{
td7
.
appendChild
(
changeStatus
(
jsonRow
));
}
else
{
let
couleurs
=
{
'
draft
'
:
'
warning
'
,
'
current
'
:
'
success
'
,
'
closed
'
:
'
muted
'
};
let
fa
=
buildColorSquare
(
jsonRow
.
status
,
couleurs
);
td7
.
innerHTML
=
fa
+
listStatus
[
statut
];
}
}
}
tr
.
appendChild
(
td7
);
let
td4
=
document
.
createElement
(
'
td
'
);
td4
.
innerHTML
=
jsonRow
.
groupe
.
nom
+
'
<br><span class="details"><i class="fas fa-user fa-fw"></i> 153</span>
'
;
tr
.
appendChild
(
td4
);
let
td2
=
document
.
createElement
(
'
td
'
);
td2
.
innerHTML
=
jsonRow
.
subject
+
'
<br>
'
+
formatStringDate
(
jsonRow
.
started_at
)
+
'
→
'
+
formatStringDate
(
jsonRow
.
ended_at
)
+
'
<br>
'
+
jsonRow
.
reference
;
tr
.
appendChild
(
td2
);
let
td3
=
document
.
createElement
(
'
td
'
);
td3
.
innerHTML
=
'
<i class="fas fa-paperclip fa-fw"></i>
'
+
jsonRow
.
offre
.
reference
;
tr
.
appendChild
(
td3
);
let
td6
=
document
.
createElement
(
'
td
'
);
td6
.
appendChild
(
displayEditLettre
(
jsonRow
));
td6
.
appendChild
(
displayDeleteLettre
(
jsonRow
));
tr
.
appendChild
(
td6
);
return
tr
;
}
/*
* Construit et affiche le formulaire d'édition
*/
function
buildEditStatusForm
()
{
let
editForm
=
document
.
createElement
(
'
form
'
);
editForm
.
setAttribute
(
'
name
'
,
'
offre_status
'
);
editForm
.
setAttribute
(
'
method
'
,
'
post
'
);
editForm
.
setAttribute
(
'
novalidate
'
,
'
1
'
);
let
divForm
=
document
.
createElement
(
'
div
'
);
divForm
.
setAttribute
(
'
id
'
,
'
offre_status
'
);
divForm
.
setAttribute
(
'
novalidate
'
,
'
novalidate
'
);
editForm
.
appendChild
(
divForm
);
let
selectForm
=
document
.
createElement
(
'
select
'
);
selectForm
.
setAttribute
(
'
name
'
,
'
lettre_status[status]
'
);
selectForm
.
classList
.
add
(
'
form-control
'
,
'
form-control-sm
'
,
'
offre_status
'
,
'
bg-warning
'
);
divForm
.
appendChild
(
selectForm
);
let
optionValue
=
{
'
draft
'
:
'
En préparation
'
,
'
current
'
:
'
Envoyer
'
};
for
(
let
value
in
optionValue
)
{
let
optionForm
=
document
.
createElement
(
'
option
'
);
optionForm
.
setAttribute
(
'
value
'
,
value
);
optionForm
.
innerHTML
=
optionValue
[
value
];
optionForm
.
classList
.
add
(
value
);
selectForm
.
appendChild
(
optionForm
);
}
return
editForm
;
}
/*
* Changement de statut pour une rangée
* @param json object jsonRow
*/
function
changeStatus
(
jsonRow
)
{
let
editForm
=
buildEditStatusForm
();
editForm
.
addEventListener
(
'
change
'
,
function
()
{
sleep
(
500
).
then
(()
=>
{
let
ask
=
confirm
(
"
Attention, une fois la lettre envoyée,
\n
"
+
"
vous ne pourrez forcément plus revenir en arrière !
\n
"
+
"
Êtes-vous sûr de vouloir changer son statut ?
"
);
if
(
ask
===
true
)
{
AJAX
(
'
POST
'
,
Routing
.
generate
(
'
api_lettre_update_status
'
,
{
'
id
'
:
jsonRow
.
id
}),
function
()
{
reloadTables
();
},
editForm
);
}
else
{
reloadTableLettre
(
'
draft
'
);
}
});
});
return
editForm
;
}
/*
* Affiche un bouton pour éditer une rangée
* @param json object jsonRow
*/
function
displayEditLettre
(
jsonRow
)
{
let
editBtn
=
buildEditBtn
();
editBtn
.
dataset
.
target
=
"
.form-lettre-modal
"
;
editBtn
.
dataset
.
lettreId
=
jsonRow
.
id
;
editBtn
.
addEventListener
(
'
click
'
,
function
()
{
let
lettreId
=
this
.
dataset
.
lettreId
;
submitURL
=
Routing
.
generate
(
'
api_lettre_update
'
,
{
'
id
'
:
lettreId
});
AJAX
(
'
GET
'
,
submitURL
,
function
(
request
)
{
let
json
=
JSON
.
parse
(
request
.
responseText
);
titleForm
.
textContent
=
'
Lettre #
'
+
lettreId
;
form
.
querySelector
(
'
#lettre_groupe
'
).
value
=
json
.
groupe
;
form
.
querySelector
(
'
#lettre_subject
'
).
value
=
json
.
subject
;
form
.
querySelector
(
'
#lettre_offre
'
).
value
=
json
.
offre
;
form
.
querySelector
(
'
#lettre_started_at
'
).
value
=
json
.
started_at
;
form
.
querySelector
(
'
#lettre_ended_at
'
).
value
=
json
.
ended_at
;
form
.
querySelector
(
'
#lettre_status
'
).
value
=
json
.
status
;
});
});
return
editBtn
;
}
/*
* Supprimer une lettre
* @param json object jsonRow
*/
function
displayDeleteLettre
(
jsonRow
)
{
let
deleteBtn
=
buildDeleteBtn
();
deleteBtn
.
dataset
.
lettreId
=
jsonRow
.
id
;
deleteBtn
.
addEventListener
(
'
click
'
,
function
()
{