diff options
Diffstat (limited to 'src/Wallabag/UserBundle')
8 files changed, 507 insertions, 1 deletions
diff --git a/src/Wallabag/UserBundle/Controller/ManageController.php b/src/Wallabag/UserBundle/Controller/ManageController.php new file mode 100644 index 00000000..92ee2b41 --- /dev/null +++ b/src/Wallabag/UserBundle/Controller/ManageController.php | |||
@@ -0,0 +1,149 @@ | |||
1 | <?php | ||
2 | |||
3 | namespace Wallabag\UserBundle\Controller; | ||
4 | |||
5 | use FOS\UserBundle\Event\UserEvent; | ||
6 | use FOS\UserBundle\FOSUserEvents; | ||
7 | use Symfony\Component\HttpFoundation\Request; | ||
8 | use Symfony\Bundle\FrameworkBundle\Controller\Controller; | ||
9 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method; | ||
10 | use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; | ||
11 | use Wallabag\UserBundle\Entity\User; | ||
12 | use Wallabag\CoreBundle\Entity\Config; | ||
13 | |||
14 | /** | ||
15 | * User controller. | ||
16 | */ | ||
17 | class ManageController extends Controller | ||
18 | { | ||
19 | /** | ||
20 | * Lists all User entities. | ||
21 | * | ||
22 | * @Route("/", name="user_index") | ||
23 | * @Method("GET") | ||
24 | */ | ||
25 | public function indexAction() | ||
26 | { | ||
27 | $em = $this->getDoctrine()->getManager(); | ||
28 | |||
29 | $users = $em->getRepository('WallabagUserBundle:User')->findAll(); | ||
30 | |||
31 | return $this->render('WallabagUserBundle:Manage:index.html.twig', array( | ||
32 | 'users' => $users, | ||
33 | )); | ||
34 | } | ||
35 | |||
36 | /** | ||
37 | * Creates a new User entity. | ||
38 | * | ||
39 | * @Route("/new", name="user_new") | ||
40 | * @Method({"GET", "POST"}) | ||
41 | */ | ||
42 | public function newAction(Request $request) | ||
43 | { | ||
44 | $userManager = $this->container->get('fos_user.user_manager'); | ||
45 | |||
46 | $user = $userManager->createUser(); | ||
47 | // enable created user by default | ||
48 | $user->setEnabled(true); | ||
49 | |||
50 | $form = $this->createForm('Wallabag\UserBundle\Form\NewUserType', $user, [ | ||
51 | 'validation_groups' => ['Profile'], | ||
52 | ]); | ||
53 | $form->handleRequest($request); | ||
54 | |||
55 | if ($form->isSubmitted() && $form->isValid()) { | ||
56 | $userManager->updateUser($user); | ||
57 | |||
58 | // dispatch a created event so the associated config will be created | ||
59 | $event = new UserEvent($user, $request); | ||
60 | $this->get('event_dispatcher')->dispatch(FOSUserEvents::USER_CREATED, $event); | ||
61 | |||
62 | $this->get('session')->getFlashBag()->add( | ||
63 | 'notice', | ||
64 | $this->get('translator')->trans('flashes.user.notice.added', ['%username%' => $user->getUsername()]) | ||
65 | ); | ||
66 | |||
67 | return $this->redirectToRoute('user_edit', array('id' => $user->getId())); | ||
68 | } | ||
69 | |||
70 | return $this->render('WallabagUserBundle:Manage:new.html.twig', array( | ||
71 | 'user' => $user, | ||
72 | 'form' => $form->createView(), | ||
73 | )); | ||
74 | } | ||
75 | |||
76 | /** | ||
77 | * Displays a form to edit an existing User entity. | ||
78 | * | ||
79 | * @Route("/{id}/edit", name="user_edit") | ||
80 | * @Method({"GET", "POST"}) | ||
81 | */ | ||
82 | public function editAction(Request $request, User $user) | ||
83 | { | ||
84 | $deleteForm = $this->createDeleteForm($user); | ||
85 | $editForm = $this->createForm('Wallabag\UserBundle\Form\UserType', $user); | ||
86 | $editForm->handleRequest($request); | ||
87 | |||
88 | if ($editForm->isSubmitted() && $editForm->isValid()) { | ||
89 | $em = $this->getDoctrine()->getManager(); | ||
90 | $em->persist($user); | ||
91 | $em->flush(); | ||
92 | |||
93 | $this->get('session')->getFlashBag()->add( | ||
94 | 'notice', | ||
95 | $this->get('translator')->trans('flashes.user.notice.updated', ['%username%' => $user->getUsername()]) | ||
96 | ); | ||
97 | |||
98 | return $this->redirectToRoute('user_edit', array('id' => $user->getId())); | ||
99 | } | ||
100 | |||
101 | return $this->render('WallabagUserBundle:Manage:edit.html.twig', array( | ||
102 | 'user' => $user, | ||
103 | 'edit_form' => $editForm->createView(), | ||
104 | 'delete_form' => $deleteForm->createView(), | ||
105 | 'twofactor_auth' => $this->getParameter('twofactor_auth'), | ||
106 | )); | ||
107 | } | ||
108 | |||
109 | /** | ||
110 | * Deletes a User entity. | ||
111 | * | ||
112 | * @Route("/{id}", name="user_delete") | ||
113 | * @Method("DELETE") | ||
114 | */ | ||
115 | public function deleteAction(Request $request, User $user) | ||
116 | { | ||
117 | $form = $this->createDeleteForm($user); | ||
118 | $form->handleRequest($request); | ||
119 | |||
120 | if ($form->isSubmitted() && $form->isValid()) { | ||
121 | $this->get('session')->getFlashBag()->add( | ||
122 | 'notice', | ||
123 | $this->get('translator')->trans('flashes.user.notice.deleted', ['%username%' => $user->getUsername()]) | ||
124 | ); | ||
125 | |||
126 | $em = $this->getDoctrine()->getManager(); | ||
127 | $em->remove($user); | ||
128 | $em->flush(); | ||
129 | } | ||
130 | |||
131 | return $this->redirectToRoute('user_index'); | ||
132 | } | ||
133 | |||
134 | /** | ||
135 | * Creates a form to delete a User entity. | ||
136 | * | ||
137 | * @param User $user The User entity | ||
138 | * | ||
139 | * @return \Symfony\Component\Form\Form The form | ||
140 | */ | ||
141 | private function createDeleteForm(User $user) | ||
142 | { | ||
143 | return $this->createFormBuilder() | ||
144 | ->setAction($this->generateUrl('user_delete', array('id' => $user->getId()))) | ||
145 | ->setMethod('DELETE') | ||
146 | ->getForm() | ||
147 | ; | ||
148 | } | ||
149 | } | ||
diff --git a/src/Wallabag/UserBundle/Entity/User.php b/src/Wallabag/UserBundle/Entity/User.php index dfed8e47..d98ae76a 100644 --- a/src/Wallabag/UserBundle/Entity/User.php +++ b/src/Wallabag/UserBundle/Entity/User.php | |||
@@ -64,7 +64,7 @@ class User extends BaseUser implements TwoFactorInterface, TrustedComputerInterf | |||
64 | protected $entries; | 64 | protected $entries; |
65 | 65 | ||
66 | /** | 66 | /** |
67 | * @ORM\OneToOne(targetEntity="Wallabag\CoreBundle\Entity\Config", mappedBy="user") | 67 | * @ORM\OneToOne(targetEntity="Wallabag\CoreBundle\Entity\Config", mappedBy="user", cascade={"remove"}) |
68 | */ | 68 | */ |
69 | protected $config; | 69 | protected $config; |
70 | 70 | ||
diff --git a/src/Wallabag/UserBundle/Form/NewUserType.php b/src/Wallabag/UserBundle/Form/NewUserType.php new file mode 100644 index 00000000..ad5a2405 --- /dev/null +++ b/src/Wallabag/UserBundle/Form/NewUserType.php | |||
@@ -0,0 +1,58 @@ | |||
1 | <?php | ||
2 | |||
3 | namespace Wallabag\UserBundle\Form; | ||
4 | |||
5 | use Symfony\Component\Form\AbstractType; | ||
6 | use Symfony\Component\Form\Extension\Core\Type\EmailType; | ||
7 | use Symfony\Component\Form\Extension\Core\Type\PasswordType; | ||
8 | use Symfony\Component\Form\Extension\Core\Type\RepeatedType; | ||
9 | use Symfony\Component\Form\Extension\Core\Type\SubmitType; | ||
10 | use Symfony\Component\Form\Extension\Core\Type\TextType; | ||
11 | use Symfony\Component\Form\FormBuilderInterface; | ||
12 | use Symfony\Component\OptionsResolver\OptionsResolver; | ||
13 | use Symfony\Component\Validator\Constraints; | ||
14 | |||
15 | class NewUserType extends AbstractType | ||
16 | { | ||
17 | public function buildForm(FormBuilderInterface $builder, array $options) | ||
18 | { | ||
19 | $builder | ||
20 | ->add('username', TextType::class, [ | ||
21 | 'required' => true, | ||
22 | 'label' => 'user.form.username_label', | ||
23 | ]) | ||
24 | ->add('plainPassword', RepeatedType::class, [ | ||
25 | 'type' => PasswordType::class, | ||
26 | 'invalid_message' => 'validator.password_must_match', | ||
27 | 'first_options' => ['label' => 'user.form.password_label'], | ||
28 | 'second_options' => ['label' => 'user.form.repeat_new_password_label'], | ||
29 | 'constraints' => [ | ||
30 | new Constraints\Length([ | ||
31 | 'min' => 8, | ||
32 | 'minMessage' => 'validator.password_too_short', | ||
33 | ]), | ||
34 | new Constraints\NotBlank(), | ||
35 | ], | ||
36 | 'label' => 'user.form.plain_password_label', | ||
37 | ]) | ||
38 | ->add('email', EmailType::class, [ | ||
39 | 'label' => 'user.form.email_label', | ||
40 | ]) | ||
41 | ->add('save', SubmitType::class, [ | ||
42 | 'label' => 'user.form.save', | ||
43 | ]) | ||
44 | ; | ||
45 | } | ||
46 | |||
47 | public function configureOptions(OptionsResolver $resolver) | ||
48 | { | ||
49 | $resolver->setDefaults([ | ||
50 | 'data_class' => 'Wallabag\UserBundle\Entity\User', | ||
51 | ]); | ||
52 | } | ||
53 | |||
54 | public function getBlockPrefix() | ||
55 | { | ||
56 | return 'new_user'; | ||
57 | } | ||
58 | } | ||
diff --git a/src/Wallabag/UserBundle/Form/UserType.php b/src/Wallabag/UserBundle/Form/UserType.php new file mode 100644 index 00000000..cfa67793 --- /dev/null +++ b/src/Wallabag/UserBundle/Form/UserType.php | |||
@@ -0,0 +1,61 @@ | |||
1 | <?php | ||
2 | |||
3 | namespace Wallabag\UserBundle\Form; | ||
4 | |||
5 | use Symfony\Component\Form\AbstractType; | ||
6 | use Symfony\Component\Form\FormBuilderInterface; | ||
7 | use Symfony\Component\OptionsResolver\OptionsResolver; | ||
8 | use Symfony\Component\Form\Extension\Core\Type\CheckboxType; | ||
9 | use Symfony\Component\Form\Extension\Core\Type\SubmitType; | ||
10 | use Symfony\Component\Form\Extension\Core\Type\TextType; | ||
11 | use Symfony\Component\Form\Extension\Core\Type\EmailType; | ||
12 | |||
13 | class UserType extends AbstractType | ||
14 | { | ||
15 | /** | ||
16 | * @param FormBuilderInterface $builder | ||
17 | * @param array $options | ||
18 | */ | ||
19 | public function buildForm(FormBuilderInterface $builder, array $options) | ||
20 | { | ||
21 | $builder | ||
22 | ->add('name', TextType::class, [ | ||
23 | 'required' => false, | ||
24 | 'label' => 'user.form.name_label', | ||
25 | ]) | ||
26 | ->add('username', TextType::class, [ | ||
27 | 'required' => true, | ||
28 | 'label' => 'user.form.username_label', | ||
29 | ]) | ||
30 | ->add('email', EmailType::class, [ | ||
31 | 'required' => true, | ||
32 | 'label' => 'user.form.email_label', | ||
33 | ]) | ||
34 | ->add('enabled', CheckboxType::class, [ | ||
35 | 'required' => false, | ||
36 | 'label' => 'user.form.enabled_label', | ||
37 | ]) | ||
38 | ->add('locked', CheckboxType::class, [ | ||
39 | 'required' => false, | ||
40 | 'label' => 'user.form.locked_label', | ||
41 | ]) | ||
42 | ->add('twoFactorAuthentication', CheckboxType::class, [ | ||
43 | 'required' => false, | ||
44 | 'label' => 'user.form.twofactor_label', | ||
45 | ]) | ||
46 | ->add('save', SubmitType::class, [ | ||
47 | 'label' => 'user.form.save', | ||
48 | ]) | ||
49 | ; | ||
50 | } | ||
51 | |||
52 | /** | ||
53 | * @param OptionsResolver $resolver | ||
54 | */ | ||
55 | public function configureOptions(OptionsResolver $resolver) | ||
56 | { | ||
57 | $resolver->setDefaults(array( | ||
58 | 'data_class' => 'Wallabag\UserBundle\Entity\User', | ||
59 | )); | ||
60 | } | ||
61 | } | ||
diff --git a/src/Wallabag/UserBundle/Resources/views/Manage/edit.html.twig b/src/Wallabag/UserBundle/Resources/views/Manage/edit.html.twig new file mode 100644 index 00000000..d5cf99c3 --- /dev/null +++ b/src/Wallabag/UserBundle/Resources/views/Manage/edit.html.twig | |||
@@ -0,0 +1,86 @@ | |||
1 | {% extends "WallabagCoreBundle::layout.html.twig" %} | ||
2 | |||
3 | {% block title %}{{ 'user.page_title'|trans }}{% endblock %} | ||
4 | |||
5 | {% block content %} | ||
6 | |||
7 | <div class="row"> | ||
8 | <div class="col s12"> | ||
9 | <div class="card-panel"> | ||
10 | <div class="row"> | ||
11 | <div class="input-field col s12"> | ||
12 | <h4>{{ 'user.edit_user'|trans }}</h4> | ||
13 | |||
14 | <div id="set6" class="col s12"> | ||
15 | {{ form_start(edit_form) }} | ||
16 | {{ form_errors(edit_form) }} | ||
17 | |||
18 | <div class="row"> | ||
19 | <div class="input-field col s12"> | ||
20 | {{ form_label(edit_form.name) }} | ||
21 | {{ form_errors(edit_form.name) }} | ||
22 | {{ form_widget(edit_form.name) }} | ||
23 | </div> | ||
24 | </div> | ||
25 | |||
26 | <div class="row"> | ||
27 | <div class="input-field col s12"> | ||
28 | {{ form_label(edit_form.username) }} | ||
29 | {{ form_errors(edit_form.username) }} | ||
30 | {{ form_widget(edit_form.username) }} | ||
31 | </div> | ||
32 | </div> | ||
33 | |||
34 | <div class="row"> | ||
35 | <div class="input-field col s12"> | ||
36 | {{ form_label(edit_form.email) }} | ||
37 | {{ form_errors(edit_form.email) }} | ||
38 | {{ form_widget(edit_form.email) }} | ||
39 | </div> | ||
40 | </div> | ||
41 | |||
42 | <div class="row"> | ||
43 | <div class="input-field col s12"> | ||
44 | {{ form_widget(edit_form.enabled) }} | ||
45 | {{ form_label(edit_form.enabled) }} | ||
46 | {{ form_errors(edit_form.enabled) }} | ||
47 | </div> | ||
48 | </div> | ||
49 | |||
50 | <div class="row"> | ||
51 | <div class="input-field col s12"> | ||
52 | {{ form_widget(edit_form.locked) }} | ||
53 | {{ form_label(edit_form.locked) }} | ||
54 | {{ form_errors(edit_form.locked) }} | ||
55 | </div> | ||
56 | </div> | ||
57 | |||
58 | {% if twofactor_auth %} | ||
59 | <div class="row"> | ||
60 | <div class="input-field col s12"> | ||
61 | {{ form_widget(edit_form.twoFactorAuthentication) }} | ||
62 | {{ form_label(edit_form.twoFactorAuthentication) }} | ||
63 | {{ form_errors(edit_form.twoFactorAuthentication) }} | ||
64 | </div> | ||
65 | </div> | ||
66 | {% endif %} | ||
67 | |||
68 | <br/> | ||
69 | |||
70 | {{ form_widget(edit_form.save, {'attr': {'class': 'btn waves-effect waves-light'}}) }} | ||
71 | {{ form_rest(edit_form) }} | ||
72 | </form> | ||
73 | <p> | ||
74 | {{ form_start(delete_form) }} | ||
75 | <button {% if app.user.id == user.id %}disabled="disabled"{% endif %} onclick="return confirm('{{ 'user.form.delete_confirm'|trans|escape('js') }}')" type="submit" class="btn waves-effect waves-light red">{{ 'user.form.delete'|trans }}</button> | ||
76 | {{ form_end(delete_form) }} | ||
77 | </p> | ||
78 | <p><a class="waves-effect waves-light btn blue-grey" href="{{ path('user_index') }}">{{ 'user.form.back_to_list'|trans }}</a></p> | ||
79 | </div> | ||
80 | </div> | ||
81 | </div> | ||
82 | </div> | ||
83 | </div> | ||
84 | </div> | ||
85 | |||
86 | {% endblock %} | ||
diff --git a/src/Wallabag/UserBundle/Resources/views/Manage/index.html.twig b/src/Wallabag/UserBundle/Resources/views/Manage/index.html.twig new file mode 100644 index 00000000..996bdb1a --- /dev/null +++ b/src/Wallabag/UserBundle/Resources/views/Manage/index.html.twig | |||
@@ -0,0 +1,48 @@ | |||
1 | {% extends "WallabagCoreBundle::layout.html.twig" %} | ||
2 | |||
3 | {% block title %}{{ 'user.page_title'|trans }}{% endblock %} | ||
4 | |||
5 | {% block content %} | ||
6 | |||
7 | <div class="row"> | ||
8 | <div class="col s12"> | ||
9 | <div class="card-panel"> | ||
10 | <div class="row"> | ||
11 | <div class="input-field col s12"> | ||
12 | <p class="help">{{ 'user.description'|trans|raw }}</p> | ||
13 | |||
14 | <table class="bordered"> | ||
15 | <thead> | ||
16 | <tr> | ||
17 | <th>{{ 'user.form.username_label'|trans }}</th> | ||
18 | <th>{{ 'user.form.email_label'|trans }}</th> | ||
19 | <th>{{ 'user.form.last_login_label'|trans }}</th> | ||
20 | <th>{{ 'user.form.locked_label'|trans }}</th> | ||
21 | <th>{{ 'user.list.actions'|trans }}</th> | ||
22 | </tr> | ||
23 | </thead> | ||
24 | <tbody> | ||
25 | {% for user in users %} | ||
26 | <tr> | ||
27 | <td>{{ user.username }}</td> | ||
28 | <td>{{ user.email }}</td> | ||
29 | <td>{% if user.lastLogin %}{{ user.lastLogin|date('Y-m-d H:i:s') }}{% endif %}</td> | ||
30 | <td>{% if user.locked %}{{ 'user.list.yes'|trans }}{% else %}{{ 'user.list.no'|trans }}{% endif %}</td> | ||
31 | <td> | ||
32 | <a href="{{ path('user_edit', { 'id': user.id }) }}">{{ 'user.list.edit_action'|trans }}</a> | ||
33 | </td> | ||
34 | </tr> | ||
35 | {% endfor %} | ||
36 | </tbody> | ||
37 | </table> | ||
38 | <br /> | ||
39 | <p> | ||
40 | <a href="{{ path('user_new') }}" class="waves-effect waves-light btn">{{ 'user.list.create_new_one'|trans }}</a> | ||
41 | </p> | ||
42 | </div> | ||
43 | </div> | ||
44 | </div> | ||
45 | </div> | ||
46 | </div> | ||
47 | |||
48 | {% endblock %} | ||
diff --git a/src/Wallabag/UserBundle/Resources/views/Manage/new.html.twig b/src/Wallabag/UserBundle/Resources/views/Manage/new.html.twig new file mode 100644 index 00000000..8c894c04 --- /dev/null +++ b/src/Wallabag/UserBundle/Resources/views/Manage/new.html.twig | |||
@@ -0,0 +1,61 @@ | |||
1 | {% extends "WallabagCoreBundle::layout.html.twig" %} | ||
2 | |||
3 | {% block title %}{{ 'user.page_title'|trans }}{% endblock %} | ||
4 | |||
5 | {% block content %} | ||
6 | |||
7 | <div class="row"> | ||
8 | <div class="col s12"> | ||
9 | <div class="card-panel"> | ||
10 | <div class="row"> | ||
11 | <div class="input-field col s12"> | ||
12 | <h4>{{ 'user.new_user'|trans }}</h4> | ||
13 | |||
14 | <div id="set6" class="col s12"> | ||
15 | {{ form_start(form) }} | ||
16 | {{ form_errors(form) }} | ||
17 | |||
18 | <div class="row"> | ||
19 | <div class="input-field col s12"> | ||
20 | {{ form_label(form.username) }} | ||
21 | {{ form_errors(form.username) }} | ||
22 | {{ form_widget(form.username) }} | ||
23 | </div> | ||
24 | </div> | ||
25 | |||
26 | <div class="row"> | ||
27 | <div class="input-field col s12"> | ||
28 | {{ form_label(form.plainPassword.first) }} | ||
29 | {{ form_errors(form.plainPassword.first) }} | ||
30 | {{ form_widget(form.plainPassword.first) }} | ||
31 | </div> | ||
32 | </div> | ||
33 | |||
34 | <div class="row"> | ||
35 | <div class="input-field col s12"> | ||
36 | {{ form_label(form.plainPassword.second) }} | ||
37 | {{ form_errors(form.plainPassword.second) }} | ||
38 | {{ form_widget(form.plainPassword.second) }} | ||
39 | </div> | ||
40 | </div> | ||
41 | |||
42 | <div class="row"> | ||
43 | <div class="input-field col s12"> | ||
44 | {{ form_label(form.email) }} | ||
45 | {{ form_errors(form.email) }} | ||
46 | {{ form_widget(form.email) }} | ||
47 | </div> | ||
48 | </div> | ||
49 | |||
50 | {{ form_widget(form.save, {'attr': {'class': 'btn waves-effect waves-light'}}) }} | ||
51 | {{ form_rest(form) }} | ||
52 | </form> | ||
53 | <p><a class="waves-effect waves-light btn blue-grey" href="{{ path('user_index') }}">{{ 'user.form.back_to_list'|trans }}</a></p> | ||
54 | </div> | ||
55 | </div> | ||
56 | </div> | ||
57 | </div> | ||
58 | </div> | ||
59 | </div> | ||
60 | |||
61 | {% endblock %} | ||
diff --git a/src/Wallabag/UserBundle/Resources/views/manage.html.twig b/src/Wallabag/UserBundle/Resources/views/manage.html.twig new file mode 100644 index 00000000..c614c55f --- /dev/null +++ b/src/Wallabag/UserBundle/Resources/views/manage.html.twig | |||
@@ -0,0 +1,43 @@ | |||
1 | {% extends "WallabagCoreBundle::layout.html.twig" %} | ||
2 | |||
3 | {% block title %}{{ 'user.manage.page_title'|trans }}{% endblock %} | ||
4 | |||
5 | {% block content %} | ||
6 | |||
7 | <div class="row"> | ||
8 | <div class="col s12"> | ||
9 | <div class="card-panel"> | ||
10 | <div class="row"> | ||
11 | <div class="input-field col s12"> | ||
12 | <p class="help">{{ 'user.manage.description'|trans|raw }}</p> | ||
13 | |||
14 | <table class="bordered"> | ||
15 | <thead> | ||
16 | <tr> | ||
17 | <th>{{ 'user.manage.field.username'|trans }}</th> | ||
18 | <th>{{ 'user.manage.field.email'|trans }}</th> | ||
19 | <th>{{ 'user.manage.field.last_login'|trans }}</th> | ||
20 | <th>{{ 'user.manage.field.locked'|trans }}</th> | ||
21 | <th>{{ 'user.manage.action'|trans }}</th> | ||
22 | </tr> | ||
23 | </thead> | ||
24 | |||
25 | <tbody> | ||
26 | {% for user in users %} | ||
27 | <tr> | ||
28 | <td>{{ user.username }}</td> | ||
29 | <td>{{ user.email }}</td> | ||
30 | <td>{{ user.lastLogin|date('d/m/Y H:i:s') }}</td> | ||
31 | <td>{{ user.locked ? 'yes' : 'no' }}</td> | ||
32 | <td>edit - delete</td> | ||
33 | </tr> | ||
34 | {% endfor %} | ||
35 | </tbody> | ||
36 | </table> | ||
37 | </div> | ||
38 | </div> | ||
39 | </div> | ||
40 | </div> | ||
41 | </div> | ||
42 | |||
43 | {% endblock %} | ||