Commit f2b7874e authored by Vassilis Kanellopoulos's avatar Vassilis Kanellopoulos Committed by kanellov

application form submission completed

parent 972f60a2
...@@ -28,6 +28,7 @@ return [ ...@@ -28,6 +28,7 @@ return [
['/school/assets', ['school'], ['get', 'post', 'delete']], ['/school/assets', ['school'], ['get', 'post', 'delete']],
['/school/labs/attachment', ['school'], ['get', 'delete']], ['/school/labs/attachment', ['school'], ['get', 'delete']],
['/application-form', ['school'], ['get', 'post']], ['/application-form', ['school'], ['get', 'post']],
['/application-form/submit-success', ['school'], ['get']],
], ],
], ],
], ],
......
...@@ -42,10 +42,10 @@ return [ ...@@ -42,10 +42,10 @@ return [
], ],
], ],
], ],
// 'app-form' => [ 'app-form' => [
// 'label' => 'Αίτηση', 'label' => 'Αίτηση',
// 'route' => 'app-form', 'route' => 'application_form',
// ], ],
], ],
], ],
......
...@@ -26,10 +26,9 @@ return function (Slim\App $app) { ...@@ -26,10 +26,9 @@ return function (Slim\App $app) {
RedBeanPHP\R::setup( RedBeanPHP\R::setup(
$container['settings']['db']['dsn'], $container['settings']['db']['dsn'],
$container['settings']['db']['user'], $container['settings']['db']['user'],
$container['settings']['db']['pass'] $container['settings']['db']['pass'],
isset($container['settings']['db']['freeze']) ? $container['settings']['db']['freeze'] : true
); );
RedBeanPHP\R::freeze();
// RedBeanPHP\R::debug( true );
$container['view'] = function ($c) { $container['view'] = function ($c) {
$settings = $c['settings']; $settings = $c['settings'];
......
...@@ -47,9 +47,18 @@ return function (Slim\App $app) { ...@@ -47,9 +47,18 @@ return function (Slim\App $app) {
return new GrEduLabs\ApplicationForm\Action\ApplicationForm( return new GrEduLabs\ApplicationForm\Action\ApplicationForm(
$c->get('view'), $c->get('view'),
$c->get(GrEduLabs\Schools\Service\AssetServiceInterface::class), $c->get(GrEduLabs\Schools\Service\AssetServiceInterface::class),
$c->get(GrEduLabs\Schools\Service\LabServiceInterface::class),
$c->get(GrEduLabs\ApplicationForm\Service\ApplicationFormServiceInterface::class), $c->get(GrEduLabs\ApplicationForm\Service\ApplicationFormServiceInterface::class),
$c->get(GrEduLabs\ApplicationForm\InputFilter\ApplicationForm::class), $c->get(GrEduLabs\ApplicationForm\InputFilter\ApplicationForm::class),
$c->get('authentication_service') $c->get('authentication_service'),
$c->get('router')->pathFor('application_form.submit_success')
);
};
$container[GrEduLabs\ApplicationForm\Action\SubmitSuccess::class] = function ($c) {
return new GrEduLabs\ApplicationForm\Action\SubmitSuccess(
$c->get('view'),
$c->get('router')->pathFor('application_form')
); );
}; };
}); });
...@@ -57,10 +66,13 @@ return function (Slim\App $app) { ...@@ -57,10 +66,13 @@ return function (Slim\App $app) {
$events('on', 'app.bootstrap', function ($stop, $app, $container) { $events('on', 'app.bootstrap', function ($stop, $app, $container) {
$container['view']->getEnvironment()->getLoader()->prependPath(__DIR__ . '/templates'); $container['view']->getEnvironment()->getLoader()->prependPath(__DIR__ . '/templates');
$app->map(['get', 'post'], '/application-form', GrEduLabs\ApplicationForm\Action\ApplicationForm::class) $app->group('/application-form', function () {
->add(GrEduLabs\Schools\Middleware\FetchSchoolFromIdentity::class) $this->map(['get', 'post'], '', GrEduLabs\ApplicationForm\Action\ApplicationForm::class)
->add(GrEduLabs\Application\Middleware\AddCsrfToView::class) ->add(GrEduLabs\Application\Middleware\AddCsrfToView::class)
->add('csrf') ->add('csrf')
->setName('application_form'); ->setName('application_form');
$this->get('/submit-success', GrEduLabs\ApplicationForm\Action\SubmitSuccess::class)
->setName('application_form.submit_success');
})->add(GrEduLabs\Schools\Middleware\FetchSchoolFromIdentity::class);
}); });
}; };
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
--
-- Table structure for table `applicationform`
--
DROP TABLE IF EXISTS `applicationform`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `applicationform` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`school_id` int(11) unsigned NOT NULL,
`apply_for` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`new_lab_perspective` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
`comments` TEXT COLLATE utf8mb4_unicode_ci,
`submitted` int(11) unsigned NOT NULL,
`submitted_by` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
PRIMARY KEY (`id`),
KEY `index_foreignkey_applicationform_school` (`school_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Table structure for table `applicationformitem`
--
DROP TABLE IF EXISTS `applicationformitem`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `applicationformitem` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`itemcategory_id` int(11) unsigned NOT NULL,
`qty` int(11) unsigned NOT NULL,
`reasons` TEXT COLLATE utf8mb4_unicode_ci NOT NULL,
`applicationform_id` int(11) unsigned NOT NULL,
`lab_id` int(11) unsigned NOT NULL,
PRIMARY KEY (`id`),
KEY `index_foreignkey_applicationformitem_itemcategory` (`itemcategory_id`),
KEY `index_foreignkey_applicationformitem_applicationform` (`applicationform_id`),
KEY `index_foreignkey_applicationformitem_lab` (`lab_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
(function () { (function ($, _, utils) {
'use strict'; 'use strict';
var ItemsView, var ItemsView,
ItemRowView, ItemRowView;
itemCount = 0;
ItemRowView = Backbone.View.extend({ ItemRowView = Backbone.View.extend({
tagName: 'tr', tagName: 'tr',
render: function (index) { render: function (index) {
this.$el.html(this.constructor.template({ index: index | 0})); this.$el.html(this.template({ index: index | 0}));
return this; return this;
} },
}, {
template: _.template($('#app-form-item-row-template').html()) template: _.template($('#app-form-item-row-template').html())
}); });
...@@ -26,9 +23,6 @@ ...@@ -26,9 +23,6 @@
}, },
initialize: function () { initialize: function () {
this.itemCount = this.$el.find('tbody tr').length; this.itemCount = this.$el.find('tbody tr').length;
if (this.itemCount === 0) {
this.addRow();
}
}, },
addRow: function () { addRow: function () {
var index = this.itemCount; var index = this.itemCount;
...@@ -45,4 +39,22 @@ ...@@ -45,4 +39,22 @@
}); });
new ItemsView(); new ItemsView();
}());
\ No newline at end of file (function () {
var form = $('#app-form form'),
messages = (function (messages) {
var itemMessages = {};
_.each(messages.items || [], function (message, idx){
var name = 'items[' + idx + ']';
_.each(_.keys(message), function (prop) {
itemMessages[name + '[' + prop + ']'] = message[prop];
});
});
delete messages.items;
_.extend(messages, itemMessages);
return messages;
}(form.data('messages')));
utils.formMessages.render(form, messages);
}());
}(window.jQuery, _, window.EDULABS.utils));
\ No newline at end of file
...@@ -12,6 +12,7 @@ namespace GrEduLabs\ApplicationForm\Action; ...@@ -12,6 +12,7 @@ namespace GrEduLabs\ApplicationForm\Action;
use GrEduLabs\ApplicationForm\Service\ApplicationFormServiceInterface; use GrEduLabs\ApplicationForm\Service\ApplicationFormServiceInterface;
use GrEduLabs\Schools\Service\AssetServiceInterface; use GrEduLabs\Schools\Service\AssetServiceInterface;
use GrEduLabs\Schools\Service\LabServiceInterface;
use Slim\Http\Request; use Slim\Http\Request;
use Slim\Http\Response; use Slim\Http\Response;
use Slim\Views\Twig; use Slim\Views\Twig;
...@@ -31,6 +32,12 @@ class ApplicationForm ...@@ -31,6 +32,12 @@ class ApplicationForm
*/ */
protected $assetsService; protected $assetsService;
/**
*
* @var LabServiceInterface
*/
protected $labService;
/** /**
* *
* @var ApplicationFormServiceInterface * @var ApplicationFormServiceInterface
...@@ -49,19 +56,28 @@ class ApplicationForm ...@@ -49,19 +56,28 @@ class ApplicationForm
*/ */
protected $authService; protected $authService;
/**
*
* @var string
*/
protected $successUrl;
public function __construct( public function __construct(
Twig $view, Twig $view,
AssetServiceInterface $assetsService, AssetServiceInterface $assetsService,
LabServiceInterface $labService,
ApplicationFormServiceInterface $appFormService, ApplicationFormServiceInterface $appFormService,
InputFilterInterface $appFormInputFilter, InputFilterInterface $appFormInputFilter,
AuthenticationServiceInterface $authService AuthenticationServiceInterface $authService,
$successUrl
) { ) {
$this->view = $view; $this->view = $view;
$this->assetsService = $assetsService; $this->assetsService = $assetsService;
$this->labService = $labService;
$this->appFormService = $appFormService; $this->appFormService = $appFormService;
$this->appFormInputFilter = $appFormInputFilter; $this->appFormInputFilter = $appFormInputFilter;
$this->authService = $authService; $this->authService = $authService;
$this->successUrl = $successUrl;
} }
public function __invoke(Request $req, Response $res) public function __invoke(Request $req, Response $res)
...@@ -75,10 +91,12 @@ class ApplicationForm ...@@ -75,10 +91,12 @@ class ApplicationForm
])); ]));
$isValid = $this->appFormInputFilter->isValid(); $isValid = $this->appFormInputFilter->isValid();
if ($isValid) { if ($isValid) {
$data = $this->appFormInputFilter->getValues(); $data = $this->appFormInputFilter->getValues();
$appForm = $this->appFormService->submit($data); $appForm = $this->appFormService->submit($data);
var_dump($appForm); $_SESSION['applicationForm']['appForm'] = $appForm;
die(); $res = $res->withRedirect($this->successUrl);
return $res;
} }
$this->view['form'] = [ $this->view['form'] = [
...@@ -87,10 +105,19 @@ class ApplicationForm ...@@ -87,10 +105,19 @@ class ApplicationForm
'raw_values' => $this->appFormInputFilter->getRawValues(), 'raw_values' => $this->appFormInputFilter->getRawValues(),
'messages' => $this->appFormInputFilter->getMessages(), 'messages' => $this->appFormInputFilter->getMessages(),
]; ];
var_dump($this->view['form']);
} }
// todo replace with labs from service
$labs = array_map(function ($bean) {
return $bean->export();
}, \RedBeanPHP\R::findAll('lab', ' school_id = ? ', [$school->id]));
// $labs = $this->labService->getLabsBySchoolId($school->id);
$res = $this->view->render($res, 'application_form/form.twig', [ $res = $this->view->render($res, 'application_form/form.twig', [
'lab_choices' => array_map(function ($lab) {
return ['value' => $lab['id'], 'label' => $lab['name']];
}, $labs),
'type_choices' => array_map(function ($category) { 'type_choices' => array_map(function ($category) {
return ['value' => $category['id'], 'label' => $category['name']]; return ['value' => $category['id'], 'label' => $category['name']];
}, $this->assetsService->getAllItemCategories()), }, $this->assetsService->getAllItemCategories()),
......
<?php
/**
* gredu_labs.
*
* @link https://github.com/eellak/gredu_labs for the canonical source repository
*
* @copyright Copyright (c) 2008-2015 Greek Free/Open Source Software Society (https://gfoss.ellak.gr/)
* @license GNU GPLv3 http://www.gnu.org/licenses/gpl-3.0-standalone.html
*/
namespace GrEduLabs\ApplicationForm\Action;
use Slim\Http\Request;
use Slim\Http\Response;
use Slim\Views\Twig;
class SubmitSuccess
{
protected $view;
protected $formUrl;
public function __construct(Twig $view, $formUrl)
{
$this->view = $view;
$this->formUrl = $formUrl;
}
public function __invoke(Request $req, Response $res)
{
$school = $req->getAttribute('school');
if (!isset($_SESSION['applicationForm']['appForm'])) {
$res = $res->withRedirect($this->formUrl);
return $res;
}
$appForm = $_SESSION['applicationForm']['appForm'];
$_SESSION['applicationForm']['appForm'] = null;
unset($_SESSION['applicationForm']['appForm']);
return $this->view->render($res, 'application_form/submit_success.twig', [
'school' => $school,
'appForm' => $appForm,
]);
}
}
...@@ -36,8 +36,8 @@ class ApplicationFormService implements ApplicationFormServiceInterface ...@@ -36,8 +36,8 @@ class ApplicationFormService implements ApplicationFormServiceInterface
$appForm->submitted_by = $data['submitted_by']; $appForm->submitted_by = $data['submitted_by'];
$items = []; $items = [];
foreach ($data['items'] as $itemData) { foreach ($data['items'] as $itemData) {
$item = R::dispense('applicationformitem'); $item = R::dispense('applicationformitem');
// $item->lab_id = $itemData['lab_id']; $item->lab_id = $itemData['lab_id'];
$item->itemcategory_id = $itemData['itemcategory_id']; $item->itemcategory_id = $itemData['itemcategory_id'];
$item->qty = $itemData['qty']; $item->qty = $itemData['qty'];
$item->reasons = $itemData['reasons']; $item->reasons = $itemData['reasons'];
......
{% extends "layout.twig" %} {% extends "layout.twig" %}
{% macro itemSelect(name, label, options, selected, index) %} {% macro itemSelect(name, label, options, selected, index) %}
<select class="form-control input-sm" name="items[{{ index | default('<%= index %>') | raw }}][{{ name }}]"> <div class="form-group">
<option value="" disabled selected>{{ label|striptags }}</option> <select class="form-control input-sm" name="items[{{ index | default('<%= index %>') | raw }}][{{ name }}]">
{% for option in options %} <option value="" disabled selected>{{ label|striptags }}</option>
<option value="{{ option.value|e }}"{% if selected == option.value %} selected{% endif %}> {% for option in options %}
{{ option.label }} <option value="{{ option.value|e }}"{% if selected == option.value %} selected{% endif %}>
</option> {{ option.label }}
{% endfor %} </option>
</select> {% endfor %}
</select>
</div>
{% endmacro %} {% endmacro %}
{% macro itemCount(name, label, value, index) %} {% macro itemCount(name, label, value, index) %}
<div class="form-group"> <div class="form-group">
<div class="col-xs-12 col-sm-12 col-md-9"> <div class="col-xs-12 col-sm-12 col-md-9">
<input placeholder="{{ label|striptags }}" class="form-control input-sm" <input placeholder="{{ label|striptags }}" class="form-control input-sm"
type="number" name="items[{{ index | default('<%= index %>') }}][{{ name }}]" value="{{ value|default('')|raw }}"> type="number" name="items[{{ index | default('<%= index %>') | raw }}][{{ name }}]" value="{{ value|default('')|raw }}">
</div> </div>
</div> </div>
{% endmacro %} {% endmacro %}
{% macro itemReasons(name, label, value, index) %}
<div class="form-group">
<textarea class="form-control input-sm" name="items[{{ index | default('<%= index %>') | raw }}][{{ name }}]"
placeholder="{{ label|striptags }}"
rows="1" cols="20">{{ value|default('') }}</textarea>
</div>
{% endmacro %}
{% macro select(name, label, options, selected) %} {% macro select(name, label, options, selected) %}
<div class="form-group"> <div class="form-group">
<label class="control-label hidden-xs hidden-sm" for="el-{{ name }}">{{ label|raw }}</label> <label class="control-label hidden-xs hidden-sm" for="el-{{ name }}">{{ label|raw }}</label>
...@@ -48,7 +58,9 @@ ...@@ -48,7 +58,9 @@
{% macro text(name, label, value) %} {% macro text(name, label, value) %}
<div class="form-group"> <div class="form-group">
<label class="control-label hidden-xs hidden-sm" for="el-{{ name }}">{{ label|raw }}</label> <label class="control-label hidden-xs hidden-sm" for="el-{{ name }}">{{ label|raw }}</label>
<textarea class="form-control" name="{{ name }}" id="el-{{ name }}" placeholder="{{ label|striptags }}">{{ value|default('') }}</textarea> <textarea class="form-control" name="{{ name }}"
id="el-{{ name }}"
placeholder="{{ label|striptags }}">{{ value|default('') }}</textarea>
</div> </div>
{% endmacro %} {% endmacro %}
...@@ -61,7 +73,8 @@ ...@@ -61,7 +73,8 @@
Αίτηση <small>για νέο εξοπλισμό</small> Αίτηση <small>για νέο εξοπλισμό</small>
{% endblock %} {% endblock %}
</h1> </h1>
<form method="post" action=""> <form method="post" action="" data-is-valid="{{ form.is_valid | default(true) ? '1' : '0' }}"
data-messages="{{ form.messages|default({})|json_encode }}">
<div class="form-group"> <div class="form-group">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent pulvinar tincidunt <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent pulvinar tincidunt
odio, vel pretium mauris imperdiet at. In tempor fermentum enim, euismod posuere odio, vel pretium mauris imperdiet at. In tempor fermentum enim, euismod posuere
...@@ -106,35 +119,39 @@ ...@@ -106,35 +119,39 @@
<div class="table-responsive"> <div class="table-responsive">
<fieldset> <fieldset>
<legend>Νέος εξοπλισμός</legend> <legend>Νέος εξοπλισμός</legend>
<div class="form-group" id="items-list"> <div id="items-list">
<table class="table table-hover table-striped"> <table class="table table-hover table-striped">
<thead> <thead>
<tr> <tr>
<th>Χώρος</th>
<th>Τύπος</th>
<th>Πλήθος</th> <th>Πλήθος</th>
<th>Τύπος</th>
<th>Χώρος</th>
<th>Αιτιολογία χρήσης</th> <th>Αιτιολογία χρήσης</th>
<th></th> <th></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for item in form.values.items %} {% for itemIndex,item in form.values.items %}
<tr> <tr>
<td>{{ macros.itemSelect('lab_id', 'Χώρος', lab_choices, item.lab_id, loop.index0 ) }}</td>
<td>{{ macros.itemSelect('itemcategory_id', 'Τύπος', type_choices, item.itemcategory_id, loop.index0) }}</td>
<td>{{ macros.itemCount('qty', 'Πλήθος', item.qty, loop.index0) }}</td> <td>{{ macros.itemCount('qty', 'Πλήθος', item.qty, loop.index0) }}</td>
<td>{{ macros.itemSelect('itemcategory_id', 'Τύπος', type_choices, item.itemcategory_id, loop.index0) }}</td>
<td>{{ macros.itemSelect('lab_id', 'Χώρος', lab_choices, item.lab_id, loop.index0 ) }}</td>
<td>{{ macros.itemReasons('reasons', 'Αιτιολογία χρήσης', item.reasons, loop.index0) }}</td>
<td> <td>
<textarea class="form-control input-sm" {% if loop.index0 > 0 %}
rows="1" cols="20" <button type="button" class="btn btn-xs text-danger remove-row">
name="items[{{ loop.index0 }}][reasons]"
placeholder="Αιτιολογία χρήσης">
{{ item.reasons }}
</textarea>
</td>
<td><button type="button" class="btn btn-xs text-danger remove-row">
<i class="fa fa-remove"></i> <i class="fa fa-remove"></i>
{% endif %}
</button</td> </button</td>
</tr> </tr>
{% else %}
<tr>
<td>{{ macros.itemCount('qty', 'Πλήθος', '', 0) }}</td>
<td>{{ macros.itemSelect('itemcategory_id', 'Τύπος', type_choices, '', 0) }}</td>
<td>{{ macros.itemSelect('lab_id', 'Χώρος', lab_choices, '', 0 ) }}</td>
<td>{{ macros.itemReasons('reasons', 'Αιτιολογία χρήσης', '', 0) }}</td>
<td></td>
</tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
<tfoot> <tfoot>
...@@ -168,12 +185,10 @@ ...@@ -168,12 +185,10 @@
<input type="hidden" name="{{ csrf.value_key }}" value="{{ csrf.value }}"> <input type="hidden" name="{{ csrf.value_key }}" value="{{ csrf.value }}">
</form> </form>