load previous app_form; app_form receipt in pdf

parent c5347d6a
This diff is collapsed.
No preview for this file type
......@@ -31,6 +31,7 @@ return [
['/school/software', ['school'], ['get', 'post', 'delete']],
['/application-form', ['school'], ['get', 'post']],
['/application-form/submit-success', ['school'], ['get']],
['/application-form/report', ['school'], ['get']],
['/tpe_survey', ['school'], ['get', 'post']],
['/tpe_survey/total-teachers', ['school'], ['post']],
['/forum', ['guest', 'user'], ['get']],
......
......@@ -10,7 +10,7 @@
*/
return [
'in_numbers' => [
'cache' => __DIR__ . '/../../data/cache/in_numbers_totals.php',
'cache' => __DIR__ . '/../../data/cache/in_numbers_totals.php',
'cache_lifetime' => 1440, // minutes
]
];
\ No newline at end of file
],
];
......@@ -62,6 +62,13 @@ return function (Slim\App $app) {
);
};
$container[GrEduLabs\ApplicationForm\Action\ApplicationFormPdf::class] = function ($c) {
return new GrEduLabs\ApplicationForm\Action\ApplicationFormPdf(
$c->get(GrEduLabs\ApplicationForm\Service\ApplicationFormServiceInterface::class),
$c->get('view')
);
};
$container[GrEduLabs\ApplicationForm\Acl\Assertion\CanSubmit::class] = function ($c) {
return new GrEduLabs\ApplicationForm\Acl\Assertion\CanSubmit(
$c->get('authentication_service'),
......@@ -89,6 +96,8 @@ return function (Slim\App $app) {
->setName('application_form');
$this->get('/submit-success', GrEduLabs\ApplicationForm\Action\SubmitSuccess::class)
->setName('application_form.submit_success');
$this->get('/report', GrEduLabs\ApplicationForm\Action\ApplicationFormPdf::class)
->setName('application_form.report');
})->add(GrEduLabs\Schools\Middleware\FetchSchoolFromIdentity::class);
});
};
/**
* 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
*/
* {
font-family: 'DejaVu Sans', Arial;
}
......@@ -57,4 +57,9 @@
utils.formMessages.render(form, messages);
}());
$('#app-form-load-modal').modal({
backdrop: 'static'
}).modal('show');
}(window.jQuery, _, window.EDULABS.utils));
\ No newline at end of file
......@@ -107,9 +107,17 @@ class ApplicationForm
];
}
$loadForm = (bool) $req->getParam('load', false);
$this->view['choose'] = !$loadForm && !$req->isPost();
if (!$req->isPost() && $loadForm) {
if (null !== ($appForm = $this->appFormService->findSchoolApplicationForm($school->id))) {
$this->view['form'] = [
'values' => $appForm,
];
}
}
$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),
......
<?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 GrEduLabs\ApplicationForm\Service\ApplicationFormServiceInterface;
use Slim\Http\Request;
use Slim\Http\Response;
use Slim\Views\Twig;
class ApplicationFormPdf
{
/**
*
* @var ApplicationFormServiceInterface
*/
protected $appFormService;
/**
*
* @var Twig
*/
protected $view;
public function __construct(ApplicationFormServiceInterface $appFormService, Twig $view)
{
$this->appFormService = $appFormService;
$this->view = $view;
}
public function __invoke(Request $req, Response $res)
{
$school = $req->getAttribute('school');
$appForm = $this->appFormService->findSchoolApplicationForm($school->id);
if (null === $appForm) {
return $res->withStatus(404);
}
$html = $this->view->fetch('application_form/pdf.twig', [
'school' => $school,
'appForm' => $appForm,
]);
$pdf = new \Dompdf\Dompdf([
'default_paper_size' => 'A4',
'default_font' => 'DejaVu Sans',
'isHtml5ParserEnabled' => true,
'is_remote_enabled' => true,
]);
$pdf->loadHtml($html);
$pdf->render();
$filename = 'edulabs_app_form_' . $appForm['id'] . '.pdf';
$str = $pdf->output();
$length = mb_strlen($str, '8bit');
return $res->withHeader('Cache-Control', 'private')
->withHeader('Content-type', 'application/pdf')
->withHeader('Content-Length', $length)
->withHeader('Content-Disposition', 'attachment; filename=' . $filename)
->withHeader('Accept-Ranges', $length)
->write($str);
}
}
......@@ -154,7 +154,7 @@
</tfoot>
</table>
</div>
{{ macros.text('comments', 'Σχόλια/Παρατηρήσεις', form.value.comments) }}
{{ macros.text('comments', 'Σχόλια/Παρατηρήσεις', form.values.comments) }}
</fieldset>
</div>
<hr>
......@@ -164,6 +164,23 @@
<input type="hidden" name="{{ csrf.name_key }}" value="{{ csrf.name }}">
<input type="hidden" name="{{ csrf.value_key }}" value="{{ csrf.value }}">
</form>
{% if choose %}
<div class="modal fade" id="app-form-load-modal" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
<p>Επιθυμείτε η νέα αίτηση να βασιστεί στη τελευταία αίτησή σας;</p>
<div class="text-right">
<button type="button" class="btn btn-default" data-dismiss="modal" aria-label="Close">
Όχι
</button>
<a class="btn btn-primary" href="{{ path_for('application_form', {}, { load: 1 }) }}">Ναι</a>
</div>
</div>
</div>
</div>
</div>
{% endif %}
<script type="text/template" id="app-form-item-row-template">
<td>{{ macros.itemCount('qty', 'Πλήθος') }}</td>
<td>{{ macros.itemSelect('itemcategory_id', 'Τύπος', type_choices) }}</td>
......
<html>
<head>
<link href="{{ base_url() }}/css/application_form/pdf.css" rel="stylesheet" type="text/css">
</head>
<body>
<div class="header">
<img src="{{ base_url() }}/img/minedu_logo.jpg">
</div>
{% include 'application_form/result.twig' %}
</body>
</html>
\ No newline at end of file
<h1 class="no-print">
{% block title %}
Επιτυχής Καταχώρηση <small>αίτησης για νέο εξοπλισμό</small>
{% endblock %}
</h1>
<p class="no-print">Η αίτηση για το σχολείο {{ school.name }} με <strong>Α/Α {{ appForm.id }}</strong>, καταχωρήθηκε επιτυχώς.</p>
<h2>Στοιχεία αίτησης</h2>
<div class="row">
<dl class="col-sm-12 col-md-6">
<dt>A/A αίτησης</dt>
<dd>{{ appForm.id }}</dd>
<dt>Ημερ. υποβολής</dt>
<dd>{{ appForm.submitted|date('d/m/Y') }}<dd>
</dl>
<dl class="col-sm-12 col-md-6">
<dt>Σχολείο</dt>
<dd>{{ school.name }}</dd>
<dt>Κωδικός Υπουργείου</dt>
<dd>{{ school.registry_no }}<dd>
</dl>
<dl class="col-lg-12">
<dt>Σχόλια/Παρατηρήσεις</dt>
<dd>{{ appForm.comments }}</dd>
</dl>
</div>
<h3>Αιτούμενος εξοπλισμός</h3>
<div class="table-responsive">
<table class="table table-striped table-hover">
<thead>
<tr>
<th>Πλήθος</th>
<th>Τύπος</th>
<th>Χώρος</th>
<th>Αιτιολογία χρήσης</th>
</tr>
</thead>
<tbody>
{% for item in appForm.items %}
<tr>
<td>{{ item.qty }}</td>
<td>{{ item.itemcategory }}</td>
<td>{{ item.lab }}</td>
<td>{{ item.reasons|e }}</td>
</tr>
{% endfor %}
</tbody>
<tfoot>
<td colspan="4"></td>
</tfoot>
</table>
</div>
......@@ -2,65 +2,14 @@
{% block content %}
<div id="app-form-success">
<h1 class="no-print">
{% block title %}
Επιτυχής Καταχώρηση <small>αίτησης για νέο εξοπλισμό</small>
{% endblock %}
</h1>
<p class="no-print">Η αίτηση για το σχολείο {{ school.name }} με <strong>Α/Α {{ appForm.id }}</strong>, καταχωρήθηκε επιτυχώς.</p>
<h2>Στοιχεία αίτησης</h2>
<div class="row">
<dl class="col-sm-12 col-md-6">
<dt>A/A αίτησης</dt>
<dd>{{ appForm.id }}</dd>
<dt>Ημερ. υποβολής</dt>
<dd>{{ appForm.submitted|date('d/m/Y') }}<dd>
</dl>
<dl class="col-sm-12 col-md-6">
<dt>Σχολείο</dt>
<dd>{{ school.name }}</dd>
<dt>Κωδικός Υπουργείου</dt>
<dd>{{ school.registry_no }}<dd>
</dl>
<dl class="col-lg-12">
<dt>Σχόλια/Παρατηρήσεις</dt>
<dd>{{ appForm.comments }}</dd>
</dl>
</div>
<h3>Αιτούμενος εξοπλισμός</h3>
<div class="table-responsive">
<table class="table table-striped table-hover">
<thead>
<tr>
<th>Πλήθος</th>
<th>Τύπος</th>
<th>Χώρος</th>
<th>Αιτιολογία χρήσης</th>
</tr>
</thead>
<tbody>
{% for item in appForm.items %}
<tr>
<td>{{ item.qty }}</td>
<td>{{ item.itemcategory }}</td>
<td>{{ item.lab }}</td>
<td>{{ item.reasons|e }}</td>
</tr>
{% endfor %}
</tbody>
<tfoot>
<td colspan="4"></td>
</tfoot>
</table>
</div>
{% include 'application_form/result.twig' %}
<div class="row no-print">
<div class="col-xs-12 text-center">
<a href="#" class="btn btn-lg btn-primary btn-print">Εκτύπωση</a>
<a href="{{ path_for('application_form.report') }}" class="btn btn-lg btn-primary btn-print">Εκτύπωση</a>
</div>
</div>
<br>
</div>
</div>
{% endblock %}
{% block htmlHead %}
......@@ -68,16 +17,4 @@
<style media="print" type="text/css">
#app-form-success .no-print {display: none;}
</style>
{% endblock %}
{% block inlinejs %}
{{ parent() }}
<script>
(function () {
$('#app-form-success').on('click', 'a.btn-print', function (evt) {
evt.preventDefault();
window.print();
});
}());
</script>
{% endblock %}
\ No newline at end of file
......@@ -113,7 +113,7 @@
</dl>
<dl class="col-lg-12">
<dt>Σχόλια/Παρατηρήσεις</dt>
<dd>{{ appForm.comments }}</dd>
<dd>{{ appForm.comments|e }}</dd>
</dl>
</div>
<h5>Αιτούμενος εξοπλισμός</h5>
......@@ -147,6 +147,9 @@
Υποβολή νέας αίτησης <sup>*</sup>
{% endif %}
</a>
<a class="btn btn-sm btn-default" href="{{ path_for('application_form.report') }}">
Εκτύπωση
</a>
<div class="text-left">
{% if appForm %}
<small class="text-muted"><sup>*</sup> Λαμβάνεται υπόψη μόνο η τελευταία αίτηση.</small>
......
......@@ -115,7 +115,7 @@ class School
$eduadminId->setRequired(false)
->getFilterChain()
->attach(new Filter\ToInt());
$creator = new Input('creator');
$creator->setRequired(true)
->getValidatorChain()
......
(function ($, _, utils) {
'use strict';
var ItemsView,
ItemRowView;
ItemRowView = Backbone.View.extend({
tagName: 'tr',
render: function (index) {
this.$el.html(this.template({ index: index | 0}));
return this;
},
template: _.template($('#app-form-item-row-template').html())
});
ItemsView = Backbone.View.extend({
el: '#items-list',
itemCount: 0,
events: {
'click .add-row': 'addRow',
'click .remove-row': 'removeRow'
},
initialize: function () {
this.itemCount = this.$el.find('tbody tr').length;
},
addRow: function () {
var index = this.itemCount;
this.itemCount += 1;
this.$el.find('tbody').append(new ItemRowView().render(index).el);
return this;
},
removeRow: function (evt) {
if (this.$el.find('tbody tr').length > 1) {
$(evt.target).closest('tr').remove();
}
return this;
}
});
new ItemsView();
(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);
}());
$('#app-form-load-modal').modal({
backdrop: 'static'
}).modal('show');
}(window.jQuery, _, window.EDULABS.utils));
\ No newline at end of file
(function (utils) {
'use strict';
var Asset,
Assets,
AssetRow,
AssetsView,
AssetView,
assetTemplate;
Asset = Backbone.Model.extend({ idAttribute: 'id' });
Assets = Backbone.Collection.extend({
model: Asset,
comparator: 'itemcategory',
});
AssetRow = Backbone.View.extend({
tagName: 'tr',
template: (function () {
if (typeof assetTemplate === 'undefined') {
assetTemplate = _.template($('#asset-row-template').html());
}
return assetTemplate;
}()),
initialize: function () {
this.model.on('change', this.render, this);
this.model.on('remove', this.remove, this);
},
render: function () {
this.$el.html(this.template({ asset: this.model.attributes }));
this.$el.attr('data-id', this.model.get('id'));
return this;
},
remove: function () {
this.$el.remove();
}
});
AssetsView = Backbone.View.extend({
el: '#school',
assetView: null,
events: {
'click .btn-add-asset': 'addAsset',
'click tbody tr': 'editAsset'
},
initialize: function () {
var that = this;
this.assetView = new AssetView({model: this.model});
_.each(this.$el.find('tbody tr'), function (tr) {
var data = $(tr).data('asset'),
asset = new Asset(data);
that.model.add(asset);
new AssetRow({ model: asset, el: tr });
$(tr).attr('data-asset', null);
});
this.model.on('add', this.renderAsset, this);
this.model.on('remove', function () {
if (this.model.length === 0) {
this.$el.find('tbody tr.no-records').show();
}
}, this);
},
addAsset: function (evt) {
evt.preventDefault();
this.assetView.render();
return this;
},
editAsset: function (evt) {
var assetId;
assetId = $(evt.target).closest('tr').data('id');
this.assetView.render(assetId);
return this;
},
renderAsset: function (asset) {
this.$el.find('tbody tr.no-records').hide();
this.$el.find('tbody').append(new AssetRow({
model: asset
}).render().el);
return this;
}
});
AssetView = Backbone.View.extend({
el: '#asset-form-modal',
form: null,
asset: null,
url: null,
events: {
'submit': 'persistAsset',
'click button.remove': 'removeAsset'
},
initialize: function () {
var that = this;
this.form = this.$el.find('form');
this.url = this.form.data('url');
this.$el.on('hide.bs.modal', function () {
utils.formMessages.clear(that.form);
that.form[0].reset();
that.form.find('input[type="hidden"]').val('');
});
},
render: function (assetId) {
var assetAttributes;
if (!assetId) {
this.$el.find('.modal-footer button.remove')
.prop('disabled', true)
.addClass('hidden');
} else {
this.$el.find('.modal-footer button.remove')
.prop('disabled', false)
.removeClass('hidden');
}
this.asset = assetId && this.model.get(assetId) || null;
assetAttributes = this.asset && this.asset.attributes || {};
_.each(this.form[0].elements, function (element) {
var element = $(element),
name = element.attr('name');
if ('checkbox' === element.attr('type')) {
element.prop('checked', utils.parseInt(assetAttributes[name]));
} else {
element.val(assetAttributes[name] || '');
}
});
this.show();
return this;
},
show: function () {
this.$el.modal('show');
return this;
},
hide: function () {
this.$el.modal('hide');
return this;
},
persistAsset: function (evt) {
var data = utils.serializeObject(this.form),
that = this;
evt.preventDefault();
$.ajax({
url: this.url,
type: 'post',
data: data,
}).done(function (response) {
if (that.asset) {
that.asset.set(response);
} else {
that.model.add(response);
}
that.hide();
}).fail(function (xhr, err) {
var messages;
if (422 === xhr.status) {
messages = JSON.parse(xhr.responseText).messages || {};
utils.formMessages.render(that.form, messages);
} else {
alert('Προέκυψε κάποιο σφάλμα');
}
});
},
removeAsset: function (evt) {
var that = this;
if (!confirm('Να διαγραφεί ο εξοπλισμός;')) {
return;
}
$.ajax({
url: that.url,
type: 'delete',
dataType: 'json',
data: {
id: that.asset.get('id')
}
}).done(function () {
that.model.remove(that.asset.get('id'));
that.hide();
}).fail(function () {
alert('Δεν ήταν δυνατή η διαγραφή του εξοπλισμού');
});
}
});
new AssetsView({ model: new Assets() });
}(window.EDULABS.utils));
\ No newline at end of file
(function () {
'use strict';
$.each($('#school .nav-tabs li'), function (index, tab) {
tab = $(tab);
if (window.location.pathname === tab.find('a').attr('href')) {
tab.addClass('active');
} else {
tab.removeClass('active');
}
});
$('[required]').parents('.form-group').find('label').append('<span>*</span>');
}());
\ No newline at end of file
(function (utils) {
'use strict';
var Lab,
Labs,
LabRow,
LabsView,
LabView,
labTemplate;
Lab = Backbone.Model.extend({ idAttribute: 'id' });
Labs = Backbone.Collection.extend({
model: Lab,
comparator: 'name'
});
LabRow = Backbone.View.extend({
tagName: 'tr',
template: (function () {
if (typeof labTemplate === 'undefined') {
labTemplate = _.template($('#lab-row-template').html());
}
return labTemplate;
}()),
initialize: function () {
this.model.on('change', this.render, this);
this.model.on('remove', this.remove, this);