school assets implemented

parent 69729892
......@@ -15,7 +15,7 @@ return [
['/school/labs', ['school'], ['get']],
['/school/staff', ['school'], ['get', 'post']],
['/school/staff/{id:[1-9][0-9]*}', ['school'], ['delete']],
['/school/assets', ['school'], ['get']],
['/school/assets', ['school'], ['get', 'post', 'delete']],
],
],
],
......
......@@ -28,7 +28,7 @@ return function (Slim\App $app) {
$container['settings']['db']['user'],
$container['settings']['db']['pass']
);
RedBeanPHP\R::freeze();
RedBeanPHP\R::freeze();
$container['view'] = function ($c) {
$settings = $c['settings'];
......
......@@ -18,6 +18,9 @@ return function (Slim\App $app) {
});
$events('on', 'app.services', function ($stop, $container) {
// actions
$container[GrEduLabs\Schools\Action\Index::class] = function ($c) {
return new GrEduLabs\Schools\Action\Index(
$c->get('view'),
......@@ -28,19 +31,19 @@ return function (Slim\App $app) {
$container[GrEduLabs\Schools\Action\Staff\ListAll::class] = function ($c) {
return new GrEduLabs\Schools\Action\Staff\ListAll(
$c->get('view'),
$c->get(GrEduLabs\Schools\Service\StaffService::class)
$c->get(GrEduLabs\Schools\Service\StaffServiceInterface::class)
);
};
$container[GrEduLabs\Schools\Action\Staff\PersistTeacher::class] = function ($c) {
return new GrEduLabs\Schools\Action\Staff\PersistTeacher(
$c->get(GrEduLabs\Schools\Service\StaffService::class)
$c->get(GrEduLabs\Schools\Service\StaffServiceInterface::class)
);
};
$container[GrEduLabs\Schools\Action\Staff\DeleteTeacher::class] = function ($c) {
return new GrEduLabs\Schools\Action\Staff\DeleteTeacher(
$c->get(GrEduLabs\Schools\Service\StaffService::class)
$c->get(GrEduLabs\Schools\Service\StaffServiceInterface::class)
);
};
......@@ -56,39 +59,75 @@ return function (Slim\App $app) {
);
};
$container[GrEduLabs\Schools\Action\Assets::class] = function ($c) {
return new GrEduLabs\Schools\Action\Assets($c->get('view'));
$container[GrEduLabs\Schools\Action\Assets\ListAssets::class] = function ($c) {
return new GrEduLabs\Schools\Action\Assets\ListAssets(
$c->get('view'),
$c->get(GrEduLabs\Schools\Service\AssetServiceInterface::class),
$c->get(GrEduLabs\Schools\Service\SchoolAssetsInterface::class),
$c->get(GrEduLabs\Schools\Service\LabServiceInterface::class)
);
};
$container[GrEduLabs\Schools\Action\Assets\PersistAsset::class] = function ($c) {
return new GrEduLabs\Schools\Action\Assets\PersistAsset(
$c->get(GrEduLabs\Schools\Service\SchoolAssetsInterface::class)
);
};
$container[GrEduLabs\Schools\Action\Assets\DeleteAsset::class] = function ($c) {
return new GrEduLabs\Schools\Action\Assets\DeleteAsset(
$c->get(GrEduLabs\Schools\Service\SchoolAssetsInterface::class)
);
};
// services
$container['schoolservice'] = function ($c) {
return new GrEduLabs\Schools\Service\SchoolService();
return $c->get(GrEduLabs\Schools\Service\SchoolServiceInterface::class);
};
$container[GrEduLabs\Schools\InputFilter\Teacher::class] = function ($c) {
return new GrEduLabs\Schools\InputFilter\Teacher();
$container['staffservice'] = function ($c) {
return $c->get(GrEduLabs\Schools\Service\StaffServiceInterface::class);
};
$container['labservice'] = function ($c) {
return $c->get(GrEduLabs\Schools\Service\LabServiceInterface::class);
};
$container[GrEduLabs\Schools\Service\StaffService::class] = function ($c) {
$container[GrEduLabs\Schools\Service\SchoolServiceInterface::class] = function ($c) {
return new GrEduLabs\Schools\Service\SchoolService();
};
$container[GrEduLabs\Schools\Service\StaffServiceInterface::class] = function ($c) {
return new GrEduLabs\Schools\Service\StaffService();
};
$container[GrEduLabs\Schools\Middleware\InputFilterTeacher::class] = function ($c) {
return new GrEduLabs\Schools\Middleware\InputFilterTeacher(
$c->get(GrEduLabs\Schools\InputFilter\Teacher::class)
$container[GrEduLabs\Schools\Service\LabServiceInterface::class] = function ($c) {
return new GrEduLabs\Schools\Service\LabService(
$c->get(GrEduLabs\Schools\Service\SchoolServiceInterface::class),
$c->get(GrEduLabs\Schools\Service\StaffServiceInterface::class)
);
};
$container['labservice'] = function ($c) {
return new GrEduLabs\Schools\Service\LabService(
$c->get('schoolservice'),
$c->get('staffservice')
$container[GrEduLabs\Schools\Service\AssetServiceInterface::class] = function ($c) {
return new GrEduLabs\Schools\Service\AssetService();
};
$container[GrEduLabs\Schools\Service\SchoolAssetsInterface::class] = function ($c) {
return $c->get(GrEduLabs\Schools\Service\AssetServiceInterface::class);
};
// middleware
$container[GrEduLabs\Schools\Middleware\InputFilterTeacher::class] = function ($c) {
return new GrEduLabs\Schools\Middleware\InputFilterTeacher(
$c->get(GrEduLabs\Schools\InputFilter\Teacher::class)
);
};
$container['assetservice'] = function ($c) {
return new GrEduLabs\Schools\Service\AssetService(
$c->get('schoolservice'),
$c->get('labservice')
$container[GrEduLabs\Schools\Middleware\InputFilterSchoolAsset::class] = function ($c) {
return new GrEduLabs\Schools\Middleware\InputFilterSchoolAsset(
$c->get(GrEduLabs\Schools\InputFilter\SchoolAsset::class)
);
};
......@@ -96,13 +135,28 @@ return function (Slim\App $app) {
return new GrEduLabs\Schools\Middleware\FetchSchoolFromIdentity($c['authentication_service']);
};
// inputfilters
$container[GrEduLabs\Schools\InputFilter\Teacher::class] = function ($c) {
return new GrEduLabs\Schools\InputFilter\Teacher();
};
$container[GrEduLabs\Schools\InputFilter\SchoolAsset::class] = function ($c) {
return new GrEduLabs\Schools\InputFilter\SchoolAsset(
$c->get(GrEduLabs\Schools\Service\LabServiceInterface::class),
$c->get(GrEduLabs\Schools\Service\AssetServiceInterface::class)
);
};
});
$events('on', 'app.bootstrap', function ($stop, $app, $container) {
$container['view']->getEnvironment()->getLoader()->prependPath(__DIR__ . '/templates');
$app->group('/school', function () {
$this->get('', GrEduLabs\Schools\Action\Index::class)->setName('school');
$this->get('/staff', GrEduLabs\Schools\Action\Staff\ListAll::class)->setName('school.staff');
$this->post('/staff', GrEduLabs\Schools\Action\Staff\PersistTeacher::class)
->add(GrEduLabs\Schools\Middleware\InputFilterTeacher::class)
......@@ -112,7 +166,12 @@ return function (Slim\App $app) {
$this->get('/labs', GrEduLabs\Schools\Action\Labs::class)->setName('school.labs');
$this->post('/labs', GrEduLabs\Schools\Action\LabCreate::class)->setName('school.labcreate');
$this->get('/assets', GrEduLabs\Schools\Action\Assets::class)->setName('school.assets');
$this->get('/assets', GrEduLabs\Schools\Action\Assets\ListAssets::class)->setName('school.assets');
$this->post('/assets', GrEduLabs\Schools\Action\Assets\PersistAsset::class)
->add(GrEduLabs\Schools\Middleware\InputFilterSchoolAsset::class);
$this->delete('/assets', GrEduLabs\Schools\Action\Assets\DeleteAsset::class);
})->add(GrEduLabs\Schools\Middleware\FetchSchoolFromIdentity::class);
});
};
......@@ -197,6 +197,69 @@ CREATE TABLE `teacher` (
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Table structure for table `itemcategory`
--
DROP TABLE IF EXISTS `itemcategory`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `itemcategory` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `name_UNIQUE` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Dumping data for table `itemcategory`
--
LOCK TABLES `itemcategory` WRITE;
/*!40000 ALTER TABLE `itemcategory` DISABLE KEYS */;
INSERT INTO `itemcategory` VALUES (8,'ACCESS POINT'),(26,'LAPTOP'),(7,'MEDIA CONVERTER'),(6,'MODEM / ROUTER '),(25,'MOTHERBOARD'),(5,'PATCH PANEL'),(4,'POWERLINE PLC'),(14,'PRINTER'),(3,'RACK'),(13,'SCANNER'),(24,'SERVER'),(12,'SPLITTER'),(2,'SWITCH/ HUB'),(23,'TABLET'),(1,'VOIP ADAPTER'),(11,'WEBCAM'),(22,'WORKSTATION'),(41,'ΒΙΝΤΕΟΠΡΟΒΟΛΕΑΣ'),(40,'ΔΙΑΔΡΑΣΤΙΚΟ ΣΥΣΤΗΜΑ'),(39,'ΔΙΑΔΡΑΣΤΙΚΟΣ ΠΙΝΑΚΑΣ'),(21,'ΕΞΩΤΕΡΙΚΟ ΜΕΣΟ ΑΠΟΘΗΚΕΥΣΗΣ'),(38,'ΕΠΕΞΕΡΓΑΣΤΗΣ (CPU)'),(20,'ΗΧΕΙΑ'),(10,'ΚΑΡΤΑ WIRELESS'),(37,'ΚΑΡΤΑ ΓΡΑΦΙΚΩΝ'),(36,'ΚΑΡΤΑ ΔΙΚΤΥΟΥ'),(35,'ΚΑΡΤΑ ΗΧΟΥ'),(9,'ΚΕΡΑΙΑ WIFI'),(34,'ΚΙΝΗΤΟ ΕΡΓΑΣΤΗΡΙΟ'),(33,'ΚΟΥΤΙ ΥΠΟΛΟΓΙΣΤΗ'),(19,'ΜΙΚΡΟΦΩΝΟ MULTIMEDIA'),(32,'ΜΝΗΜΗ RAM'),(31,'ΟΔΗΓΟΙ ΟΠΤΙΚΩΝ ΜΕΣΩΝ'),(30,'ΟΘΟΝΗ'),(18,'ΠΛΗΚΤΡΟΛΟΓΙΟ'),(17,'ΠΟΝΤΙΚΙ'),(29,'ΣΚΛΗΡΟΣ ΔΙΣΚΟΣ'),(16,'ΣΤΑΘΕΡΟΠΟΙΗΤΕΣ ΤΑΣΗΣ & U.P.S'),(28,'ΣΥΣΤΗΜΑ ΤΗΛΕΔΙΑΣΚΕΨΗΣ'),(27,'ΤΡΟΦΟΔΟΤΙΚΟ'),(15,'ΨΗΦ. ΦΩΤΟΓΡΑΦΙΚΗ/ΒΙΝΤΕΟΚΑΜΕΡΑ');
/*!40000 ALTER TABLE `itemcategory` ENABLE KEYS */;
UNLOCK TABLES;
--
-- Table structure for table `lab`
--
DROP TABLE IF EXISTS `lab`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `lab` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Table structure for table `schoolasset`
--
DROP TABLE IF EXISTS `schoolasset`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `schoolasset` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`itemcategory_id` int(11) unsigned NOT NULL,
`school_id` int(11) unsigned NOT NULL,
`qty` int(11) unsigned NOT NULL,
`lab_id` int(11) unsigned NOT NULL,
`acquisition_year` char(4) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`comments` text COLLATE utf8mb4_unicode_ci,
PRIMARY KEY (`id`),
KEY `index_foreignkey_schoolasset_itemcategory` (`itemcategory_id`),
KEY `index_foreignkey_schoolasset_school` (`school_id`),
KEY `index_foreignkey_schoolasset_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 */;
......
(function () {
(function (utils) {
'use strict';
var Asset,
Assets,
AssetView,
AssetRow,
AssetsView,
AssetModalView,
AssetView,
assetTemplate;
Asset = Backbone.Model.extend({ idAttribute: 'id' });
Assets = Backbone.Collection.extend({
model: Asset,
comparator: 'name',
comparator: 'itemcategory',
});
AssetView = Backbone.View.extend({
AssetRow = Backbone.View.extend({
tagName: 'tr',
template: (function () {
if (typeof assetTemplate === 'undefined') {
......@@ -25,66 +25,109 @@
}()),
initialize: function () {
this.model.on('change', this.render, this);
this.model.on('remove', this.remove, this);
},
render: function () {
var html = this.template({ asset: this.model.attributes });
this.$el.html(this.template({ asset: this.model.attributes }));
this.$el.attr('data-id', this.model.get('id'));
this.$el.html(html);
return this;
},
remove: function () {
this.$el.remove();
}
});
AssetsView = Backbone.View.extend({
el: '#school',
modal: null,
assetView: null,
events: {
'click .btn-add-asset': 'addAsset',
'click tbody tr': 'editAsset'
},
initialize: function () {
var that = this;
this.modal = new AssetModalView();
_.each(this.$el.find('tbody tr[data-asset]'), function (tr) {
var data,
asset;
tr = $(tr);
data = tr.data('asset');
asset = new Asset(data);
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 AssetView({ model: asset });
tr.attr('data-asset', null);
new AssetRow({ model: asset, el: tr });
$(tr).attr('data-asset', null);
});
this.model.on('add', this.renderAsset, this);
},
renderAsset: function (asset) {
this.$el.find('tbody').append(new AssetView({
model: asset
}).render().el);
return this;
this.model.on('remove', function () {
if (this.model.length === 0) {
this.$el.find('tbody tr.no-records').show();
}
}, this);
},
addAsset: function (evt) {
var that = this;
evt.preventDefault();
this.modal.render(function (data) {
that.model.add(data);
});
this.assetView.render();
return this;
},
editAsset: function (evt) {
var asset = this.model.get($(evt.target).closest('tr').data('id'));
this.modal.render(function (data) {
asset.set(data);
}, asset.attributes);
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;
}
});
AssetModalView = Backbone.View.extend({
AssetView = Backbone.View.extend({
el: '#asset-form-modal',
form: null,
asset: null,
url: null,
events: {
'submit': 'submit',
'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');
......@@ -94,43 +137,52 @@
this.$el.modal('hide');
return this;
},
render: function (done, asset) {
var template,
persistAsset: function (evt) {
var data = utils.serializeObject(this.form),
that = this;
asset = asset || {};
this.form[0].reset();
this.form.find('input[type="hidden"]').val('');
this.form.data('done', done);
_.each(this.form[0].elements, function (element) {
var element = $(element),
name = element.attr('name');
if (typeof asset[name] !== undefined) {
element.val(asset[name]);
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('Προέκυψε κάποιο σφάλμα');
}
});
this.show();
return this;
},
submit: function (evt) {
var data;
evt.preventDefault();
data = _.reduce(this.form.serializeArray(), function (hash, pair) {
hash[pair.name] = pair.value;
return hash;
}, {});
evt.preventDefault();
if (!data.id) {
data.id = (100 * Math.random()).toFixed(0);
removeAsset: function (evt) {
var that = this;
if (!confirm('Να διαγραφεί ο εξοπλισμός;')) {
return;
}
$.ajax({
url: that.url,
type: 'delete',
dataType: 'json',
data: {
id: that.asset.get('id'),
}
this.form.data('done')(data);
this.form.data('done', undefined);
this.hide();
}
}).done(function () {
that.model.remove(that.asset.get('id'));
that.hide();
}).fail(function () {
alert('Δεν ήταν δυνατή η διαγραφή του εξοπλισμού');
});
}
});
new AssetsView({ model: new Assets() });
}());
\ No newline at end of file
}(window.EDULABS.utils));
\ No newline at end of file
......@@ -84,7 +84,7 @@
url: null,
events: {
'submit form': 'persistTeacher',
'click button.remove': 'removeTeacher',
'click button.remove': 'removeTeacher'
},
initialize: function () {
var that = this;
......@@ -99,9 +99,13 @@
render: function (teacherId) {
var teacherAttributes;
if (!teacherId) {
this.$el.find('.modal-footer button.remove').addClass('hidden');
this.$el.find('.modal-footer button.remove')
.prop('disabled', true)
.addClass('hidden');
} else {
this.$el.find('.modal-footer button.remove').removeClass('hidden');
this.$el.find('.modal-footer button.remove')
.prop('disabled', false)
.removeClass('hidden');
}
this.teacher = teacherId && this.model.get(teacherId) || null;
teacherAttributes = this.teacher && this.teacher.attributes || {};
......@@ -115,18 +119,19 @@
}
});
this.show();
return this;
},
show: function () {
this.$el.modal('show');
return this;
},
hide: function () {
this.$el.modal('hide');
return this;
},
persistTeacher: function (evt) {
var data = _.reduce(this.form.serializeArray(), function (hash, pair) {
hash[pair.name] = pair.value;
return hash;
}, {});
var data = utils.serializeObject(this.form);
var that = this;
evt.preventDefault();
$.ajax({
......
<?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\Schools\Action\Assets;
use Exception;
use GrEduLabs\Schools\Service\SchoolAssetsInterface;
use Slim\Http\Request;
use Slim\Http\Response;
class DeleteAsset
{
/**
*
* @var SchoolAssetsInterface
*/
private $schoolAssetsService;
public function __construct(SchoolAssetsInterface $schoolAssetsService)
{
$this->schoolAssetsService = $schoolAssetsService;
}
public function __invoke(Request $req, Response $res)
{
$school = $req->getAttribute('school', false);
if (!$school->id) {
return $res->withStatus(403, 'No school');
}
$id = $req->getParam('id', false);
if (!$id) {
$res = $res->withStatus(404);
return $res;
}
try {
$this->schoolAssetsService->removeAssetFromSchool($school->id, $id);
$res = $res->withStatus(204);
} catch (Exception $ex) {
$res = $res->withStatus(500, $ex->getMessage());
}
return $res;
}
}
<?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\Schools\Action\Assets;
use GrEduLabs\Schools\Service\AssetServiceInterface;
use GrEduLabs\Schools\Service\LabServiceInterface;
use GrEduLabs\Schools\Service\SchoolAssetsInterface;
use Slim\Http\Request;
use Slim\Http\Response;
use Slim\Views\Twig;
class ListAssets
{
/**
*
* @var Twig
*/
protected $view;
/**
*
* @var AssetServiceInterface
*/
protected $assetsService;
/**
*
* @var SchoolAssetsInterface
*/
protected $schoolAssetsService;
/**
*