sync on demand action

parent 2daa66d0
......@@ -34,6 +34,7 @@ return [
['/tpe_survey', ['school'], ['get', 'post']],
['/tpe_survey/total-teachers', ['school'], ['post']],
['/forum', ['guest', 'user'], ['get']],
['/sch_sync/sync', ['school'], ['get']],
],
],
],
......
......@@ -14,6 +14,7 @@ return [
__DIR__ . '/../../module/schools/public',
__DIR__ . '/../../module/application_form/public',
__DIR__ . '/../../module/tpe_survey/public',
__DIR__ . '/../../module/sch_sync/public',
],
],
];
......@@ -185,7 +185,6 @@ CREATE TABLE `lab` (
`school_id` int(11) unsigned NOT NULL,
`name` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
`labtype_id` int(11) unsigned NOT NULL,
`is_new` tinyint(1) unsigned DEFAULT 0,
`responsible_id` int(11) unsigned DEFAULT NULL,
`area` int(11) unsigned DEFAULT NULL,
`attachment` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
......@@ -194,14 +193,17 @@ CREATE TABLE `lab` (
`has_server` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`use_ext_program` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`use_in_program` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`is_new` tinyint(1) unsigned DEFAULT NULL,
`inventory_key` int(11) unsigned DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `index_foreignkey_lab_school` (`school_id`),
KEY `index_foreignkey_lab_labtype` (`labtype_id`),
KEY `index_foreignkey_lab_responsible` (`responsible_id`),
CONSTRAINT `c_fk_lab_school_id` FOREIGN KEY (`school_id`) REFERENCES `school` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `c_fk_lab_labtype_id` FOREIGN KEY (`labtype_id`) REFERENCES `labtype` (`id`) ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT `c_fk_lab_responsible_id` FOREIGN KEY (`responsible_id`) REFERENCES `teacher` (`id`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
KEY `index_lab_inventory_key` (`inventory_key`),
CONSTRAINT `c_fk_lab_labtype_id` FOREIGN KEY (`labtype_id`) REFERENCES `labtype` (`id`) ON UPDATE CASCADE,
CONSTRAINT `c_fk_lab_responsible_id` FOREIGN KEY (`responsible_id`) REFERENCES `teacher` (`id`) ON DELETE SET NULL ON UPDATE CASCADE,
CONSTRAINT `c_fk_lab_school_id` FOREIGN KEY (`school_id`) REFERENCES `school` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
......
......@@ -50,24 +50,45 @@ return function (App $app) {
$c->get('logger')
);
};
$container[CreateLabs::class] = function ($c) {
$container[\SchSync\SyncFromInventory::class] = function ($c) {
$settings = $c->get('settings');
$categoryMap = isset($settings['inventory']['category_map'])
? $settings['inventory']['category_map'] : [];
return new CreateLabs(
return new \SchSync\SyncFromInventory(
$c->get(LabServiceInterface::class),
$c->get(AssetServiceInterface::class),
$c->get('SchInventory\\Service'),
$c->get(SchoolServiceInterface::class),
$c->get('authentication_service'),
$c->get('logger'),
$categoryMap
);
};
$container[CreateLabs::class] = function ($c) {
return new CreateLabs(
$c->get(LabServiceInterface::class),
$c->get(\SchSync\SyncFromInventory::class),
$c->get('authentication_service')
);
};
$container[SchSync\Action\Sync::class] = function ($c) {
return new SchSync\Action\Sync(
$c->get(\SchSync\SyncFromInventory::class),
$c->get('authentication_service')
);
};
});
$events('on', 'app.bootstrap', function ($app, $container) {
$app->get('/sch_sync/sync', SchSync\Action\Sync::class)->setName('sch_sync/sync');
});
$events('on', 'app.bootstrap', function ($app, $container) {
$container['view']->getEnvironment()->getLoader()->prependPath(__DIR__ . '/templates');
$container['router']->getNamedRoute('user.login.sso')
->add(CreateUser::class)
->add(CreateSchool::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
*/
(function ($, document) {
$('#inventory_sync').on('click', function (evt) {
var that = $(this),
url = that.data('href');
that.prop('disabled', true);
that.find('i').addClass('fa-spinner fa-spin');
$.ajax({
url: url,
type: 'get'
}).done(function (response) {
document.location.reload(true);
}).fail(function (xhr, err) {
alert('Προέκυψε κάποιο σφάλμα κατά την εισαγωγή. Παρακαλώ δοκιμάστε ξανά.');
that.prop('disabled', false);
that.find('i').removeClass('fa-spinner fa-spin');
});
});
} (window.jQuery, document));
\ No newline at end of file
<?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 SchSync\Action;
use RedBeanPHP\R;
use Slim\Http\Request;
use Slim\Http\Response;
use Zend\Authentication\AuthenticationServiceInterface;
class Sync
{
/**
*
* @var AuthenticationServiceInterface
*/
protected $authService;
/**
*
* @var callable
*/
protected $syncFromInventory;
public function __construct(
callable $syncFromInventory,
AuthenticationServiceInterface $authService
) {
$this->syncFromInventory = $syncFromInventory;
$this->authService = $authService;
}
public function __invoke(Request $req, Response $res)
{
$identity = $this->authService->getIdentity();
if (null === $identity) {
return $res;
}
$user = R::load('user', $identity->id);
if (!$user->school_id) {
return $res;
}
$school_id = $user->school_id;
$sync = $this->syncFromInventory;
$result = $sync($school_id);
if (false === $result) {
return $res->withStatus(500);
}
return $res->withJson($result);
}
}
......@@ -10,13 +10,8 @@
namespace SchSync\Middleware;
use Exception;
use GrEduLabs\Schools\Service\AssetServiceInterface;
use GrEduLabs\Schools\Service\LabServiceInterface;
use GrEduLabs\Schools\Service\SchoolServiceInterface;
use Psr\Log\LoggerInterface;
use RedBeanPHP\R;
use SchInventory\ServiceInterface as InventoryService;
use Slim\Http\Request;
use Slim\Http\Response;
use Zend\Authentication\AuthenticationServiceInterface;
......@@ -31,55 +26,24 @@ class CreateLabs
/**
*
* @var AssetServiceInterface
* @var callable
*/
protected $assetService;
/**
*
* @var InventoryService
*/
protected $inventoryService;
/**
*
* @var SchoolServiceInterface
*/
protected $schoolService;
protected $syncFromInventory;
/**
*
* @var AuthenticationServiceInterface
*/
protected $authService;
/**
* @var LoggerInterface
*/
private $logger;
/**
*
* @var array
*/
private $categoryMap;
public function __construct(
LabServiceInterface $labService,
AssetServiceInterface $assetService,
InventoryService $inventoryService,
SchoolServiceInterface $schoolService,
AuthenticationServiceInterface $authService,
LoggerInterface $logger,
array $categoryMap = []
callable $syncFromInventory,
AuthenticationServiceInterface $authService
) {
$this->labService = $labService;
$this->assetService = $assetService;
$this->inventoryService = $inventoryService;
$this->schoolService = $schoolService;
$this->authService = $authService;
$this->logger = $logger;
$this->categoryMap = $categoryMap;
$this->labService = $labService;
$this->syncFromInventory = $syncFromInventory;
$this->authService = $authService;
}
public function __invoke(Request $req, Response $res, callable $next)
......@@ -96,75 +60,12 @@ class CreateLabs
}
$school_id = $user->school_id;
$school = $this->schoolService->getSchool($school_id);
if (0 < count($this->labService->getLabsBySchoolId($school_id))) {
return $res;
}
try {
$equipment = $this->inventoryService->getUnitEquipment($school['registry_no']);
} catch (Exception $e) {
$this->logger->error(sprintf('Problem retrieving assets from inventory for school %s', $school_id));
$this->logger->debug('Exception', [$e->getMessage(), $e->getTraceAsString()]);
return $res;
}
$labTypes = array_reduce($this->labService->getLabTypes(), function ($map, $type) {
$map[trim($type['name'])] = $type['id'];
return $map;
}, []);
$assetTypes = array_reduce($this->assetService->getAllItemCategories(), function ($map, $type) {
$map[trim($type['name'])] = $type['id'];
return $map;
}, []);
try {
$locations = array_reduce($equipment, function ($uniq, $item) use ($school_id, $labTypes, $assetTypes) {
if (!isset($uniq[$item['location.id']])) {
$locationName = $item['location.name'];
$detected = reset(array_filter(array_keys($labTypes), function ($type) use ($locationName) {
return false !== stripos($locationName, $type) ||
false !== stripos($type, $locationName);
}));
$labType = $detected ? $labTypes[$detected] : end($labTypes);
$data = [
'school_id' => (int) $school_id,
'name' => $locationName,
'labtype_id' => (int) $labType,
];
$lab = R::dispense('lab');
$lab->import($data);
$uniq[$item['location.id']] = $lab;
}
$categoryName = $item['item_template.category.name'];
$type = reset(array_filter(array_keys($this->categoryMap), function ($type) use ($categoryName) {
return $type == $categoryName;
}));
$type = ($type) ? $assetTypes[$this->categoryMap[$type]] : false;
if ($type !== false) {
if (!isset($uniq[$item['location.id']]->ownSchoolAsset[$type])) {
$asset = R::dispense('schoolasset');
$asset->school_id = (int) $school_id;
$asset->itemcategory_id = (int) $type;
$uniq[$item['location.id']]->ownSchoolAsset[$type] = $asset;
}
$uniq[$item['location.id']]->ownSchoolAsset[$type]->qty += 1;
}
return $uniq;
}, []);
R::storeAll($locations);
$this->logger->info(sprintf('Add assets from inventory for school %s', $school_id));
} catch (Exception $e) {
$this->logger->error(sprintf('Problem inserting assets for school %s in database', $school_id));
$this->logger->debug('Exception', [$e->getMessage(), $e->getTraceAsString()]);
}
$sync = $this->syncFromInventory;
$sync($school_id);
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 SchSync;
use Exception;
use GrEduLabs\Schools\Service\AssetServiceInterface;
use GrEduLabs\Schools\Service\LabServiceInterface;
use GrEduLabs\Schools\Service\SchoolServiceInterface;
use Psr\Log\LoggerInterface;
use RedBeanPHP\R;
use SchInventory\ServiceInterface as InventoryService;
class SyncFromInventory
{
/**
*
* @var LabServiceInterface
*/
protected $labService;
/**
*
* @var AssetServiceInterface
*/
protected $assetService;
/**
*
* @var InventoryService
*/
protected $inventoryService;
/**
*
* @var SchoolServiceInterface
*/
protected $schoolService;
/**
* @var LoggerInterface
*/
private $logger;
/**
*
* @var array
*/
private $categoryMap;
public function __construct(
LabServiceInterface $labService,
AssetServiceInterface $assetService,
InventoryService $inventoryService,
SchoolServiceInterface $schoolService,
LoggerInterface $logger,
array $categoryMap = []
) {
$this->labService = $labService;
$this->assetService = $assetService;
$this->inventoryService = $inventoryService;
$this->schoolService = $schoolService;
$this->logger = $logger;
$this->categoryMap = $categoryMap;
}
public function __invoke($school_id)
{
$school = $this->schoolService->getSchool($school_id);
try {
$equipment = $this->inventoryService->getUnitEquipment($school['registry_no']);
} catch (Exception $e) {
$this->logger->error(sprintf('Problem retrieving assets from inventory for school %s', $school_id));
$this->logger->debug('Exception', [$e->getMessage(), $e->getTraceAsString()]);
return false;
}
$labTypes = $this->getLabTypes();
$assetTypes = $this->getAssetTypes();
try {
$locations = $this->getLocations($school_id, $equipment, $labTypes, $assetTypes);
R::storeAll($locations);
$this->logger->info(sprintf('Add assets from inventory for school %s', $school_id));
return $this->labService->getLabsBySchoolId($school_id);
} catch (Exception $e) {
$this->logger->error(sprintf('Problem inserting assets for school %s in database', $school_id));
$this->logger->debug('Exception', [$e->getMessage(), $e->getTraceAsString()]);
return false;
}
}
private function getLabTypes()
{
return array_reduce($this->labService->getLabTypes(), function ($map, $type) {
$map[trim($type['name'])] = $type['id'];
return $map;
}, []);
}
private function getAssetTypes()
{
return array_reduce($this->assetService->getAllItemCategories(), function ($map, $type) {
$map[trim($type['name'])] = $type['id'];
return $map;
}, []);
}
private function getLocations($school_id, array $equipment, array $labTypes, array $assetTypes)
{
return array_reduce($equipment, function ($uniq, $item) use ($school_id, $labTypes, $assetTypes) {
if (!isset($uniq[$item['location.id']])) {
$locationName = $item['location.name'];
$locationId = $item['location.id'];
$lab = R::findOne('lab', ' school_id = ? AND (inventory_key = ? OR name = ?)', [
$school_id,
$locationId,
$locationName,
]);
if (null !== $lab) {
return $uniq;
}
$detected = reset(array_filter(array_keys($labTypes), function ($type) use ($locationName) {
return false !== stripos($locationName, $type) ||
false !== stripos($type, $locationName);
}));
$labType = $detected ? $labTypes[$detected] : end($labTypes);
$data = [
'school_id' => (int) $school_id,
'name' => $locationName,
'labtype_id' => (int) $labType,
'inventory_key' => (int) $locationId,
];
$lab = R::dispense('lab');
$lab->import($data);
$uniq[$item['location.id']] = $lab;
}
$categoryName = $item['item_template.category.name'];
$type = reset(array_filter(array_keys($this->categoryMap), function ($type) use ($categoryName) {
return $type == $categoryName;
}));
$type = ($type) ? $assetTypes[$this->categoryMap[$type]] : false;
if ($type !== false) {
if (!isset($uniq[$item['location.id']]->ownSchoolAsset[$type])) {
$asset = R::dispense('schoolasset');
$asset->school_id = (int) $school_id;
$asset->itemcategory_id = (int) $type;
$uniq[$item['location.id']]->ownSchoolAsset[$type] = $asset;
}
$uniq[$item['location.id']]->ownSchoolAsset[$type]->qty += 1;
}
return $uniq;
}, []);
}
}
{% extends "schools/index.twig" %}
{% import "schools/form.twig" as macros %}
{% block schoolTitle %}
{{ parent() }} <small>Χώροι</small>
{% endblock %}
{% block navItems %}
<li role="presentation" class="pull-right">
<a href="#" class="btn btn-primary btn-add-lab" title="Καταχώρηση χώρου">
<i class="fa fa-plus"></i>
<span class="hidden-xs">Καταχώρηση χώρου</span>
</a>
</li>
{% endblock %}
{% block schoolContent %}
<div id="school-labs">
<p>
Σε αυτήν τη καρτέλα εμφανίζονται χώροι που χρησιμοποιούνται ήδη για
ΤΠΕ και έχουν δηλωθεί σε άλλα πληροφοριακά συστήματα του ΥΠΠΕΘ.
Επίσης, μπορείτε να καταχωρήσετε νέους χώρους από το πλήκτρο
«καταχώρηση χώρου», που θα θέλατε να χρησιμοποιήσετε για χρήση
ΤΠΕ (πχ μια διαθέσιμη αίθουσα διδασκαλίας για τη δημιουργία ενός
νέου εργαστηρίου πληροφορικής ή το εργαστήριο Τεχνολογίας το οποίο
θα θέλατε να εξοπλίσετε με ένα Η/Υ και ένα βιντεοπροβολέα ή
οποιαδήποτε άλλη αίθουσα για την οποία θα ζητήσετε εξοπλισμό).
Σε κάθε περίπτωση θα πρέπει να τεκμηριωθεί η χρήση της αίθουσας
για κάθε ένα από τα μαθήματα που θα χρησιμοποιείται συμπληρώνοντας
τα αντίστοιχα πεδία.
</p>
<p>
Σε κάθε περίπτωση θα πρέπει να δικαιολογηθεί η χρήση της αίθουσας
συμπληρώνοντας όλα τα πεδία.
</p>
<p>
<button data-href="{{ path_for('sch_sync/sync') }}" class="btn btn-primary" id="inventory_sync"><i class="fa fa-copy"></i> Ενημέρωση από το Κτηματολόγιο</button>
</p>
<div class="table-responsive">
<table class="table table-hover table-striped">
<thead>
<tr>
<th>Ονομασία</th>
<th>Τύπος</th>
<th>Δημιουργία νέου χώρου</th>
<th>Υπεύθυνος</th>
<th>Δίκτυο</th>
<th>Server</th>
<th>Επιφάνεια (m<sup>2</sup>)</th>
</tr>
</thead>
<tbody>
{% for lab in labs %}
<tr data-lab="{{ lab|json_encode }}" data-id="{{ lab.id }}">
<td>{{ lab.name }}</td>
<td>{{ lab.labtype }}</td>
<td>{{ lab.is_new ? 'ΝΑΙ' : 'ΟΧΙ' }}</td>
<td>{{ lab.responsible }}</td>
<td>{{ lab.has_network }}</td>
<td>{{ lab.has_server }}</td>
<td>{{ lab.area }}</td>
</tr>
{% else %}
<tr>
<td colspan="7" class="no-records text-center text-muted">
Δεν έχουν καταχωρηθεί χώροι.
</td>
</tr>
{% endfor %}
</tbody>
<tfoot>
<tr>
<td colspan="7"></td>
</tr>
</tfoot>
</table>
</div>
<div class="modal fade" id="lab-form-modal" role="dialog" aria-labelledby="lab-from">
<form class="form-horizontal" method="post" action="{{ path_for('school.labs') }}"
data-url="{{ path_for('school.labs') }}" enctype="multipart/form-data">
<div class="modal-dialog" role="form">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
<h4 class="modal-title">Στοιχεία χώρου</h4>
</div>
<div class="modal-body">
{{ macros.input('name', 'Όνομα', '', 'text', {'required': ''}) }}
{{ macros.select('responsible_id', 'Υπεύθυνος', staff, '', {'required': ''}) }}
{{ macros.select('labtype_id', 'Τύπος', lab_types, '', {'required': ''}) }}
{{ macros.checkbox('is_new', 'Δημιουργία νέου χώρου') }}
{{ macros.select('has_network', 'Δίκτυο', network_options, '', {'required': ''}) }}
{{ macros.select('has_server', 'Ύπαρξη server', server_options, '', {'required': ''}) }}
{{ macros.input('area', 'Επιφάνεια (m<sup>2</sup>)', '', 'number', {'required': '', 'min': 0, 'max': 500}) }}
{{ macros.file('attachment', 'Αρχείο κάτοψης ή φωτογραφία', path_for('school.labs.attachment', {}, {'lab_id': '__lab_id__'})) }}
{{ macros.select('lessons', 'Μαθήματα', lessons_options, '', {'multiple': ''}) }}
<small class="help-block pull-right">Κρατήστε πατημένο το Ctrl για να επιλέξετε περισσότερα από ένα μαθήματα</small>
{{ macros.text('use_in_program', 'Χρήση στα πλαίσια μαθημάτων') }}
{{ macros.text('use_ext_program', 'Χρήση για δραστηριότητες εκτός εκπαιδευτικού προγράμματος') }}
<input type="hidden" name="id" value="">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-danger pull-left remove">Διαγραφή</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Κλείσιμο</button>
<button name="submit" value="submit" type="submit" class="btn btn-primary">Αποθήκευση</button>
</div>
</div>
</div>
</form>
</div>
<script type="text/template" id="lab-row-template">
<td><%= lab.name %></td>
<td><%= lab.labtype %></td>
<td><%= parseInt(lab.is_new, 10) ? 'ΝΑΙ' : 'OXI' %></td>
<td><%= lab.responsible %></td>
<td><%= lab.has_network %></td>
<td><%= lab.has_server %></td>
<td><%= lab.area %></td>
</script>
</div>
{% endblock %}
{% block htmlHead %}
{{ parent() }}
<link rel="stylesheet" href="{{ base_url }}/css/jquery.fileupload.css">
{% endblock %}
{% block inlinejs %}
{{ parent() }}
<script src="{{ base_url }}/js/jquery.ui.widget.js"></script>
<script src="{{ base_url }}/js/jquery.iframe-transport.js"></script>
<script src="{{ base_url }}/js/jquery.fileupload.js"></script>
<script src="{{ base_url }}/js/schools/labs.js"></script>
<script src="{{ base_url }}/js/sch_sync/sync.js"></script>
{% endblock %}
\ No newline at end of file
......@@ -124,7 +124,6 @@ CREATE TABLE `lab` (
`school_id` int(11) unsigned NOT NULL,
`name` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
`labtype_id` int(11) unsigned NOT NULL,
`is_new` tinyint(1) unsigned DEFAULT 0,
`responsible_id` int(11) unsigned DEFAULT NULL,
`area` int(11) unsigned DEFAULT NULL,
`attachment` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
......@@ -133,14 +132,17 @@ CREATE TABLE `lab` (
`has_server` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`use_ext_program` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`use_in_program` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`is_new` tinyint(1) unsigned DEFAULT NULL,
`inventory_key` int(11) unsigned DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `index_foreignkey_lab_school` (`school_id`),
KEY `index_foreignkey_lab_labtype` (`labtype_id`),
KEY `index_foreignkey_lab_responsible` (`responsible_id`),
CONSTRAINT `c_fk_lab_school_id` FOREIGN KEY (`school_id`) REFERENCES `school` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `c_fk_lab_labtype_id` FOREIGN KEY (`labtype_id`) REFERENCES `labtype` (`id`) ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT `c_fk_lab_responsible_id` FOREIGN KEY (`responsible_id`) REFERENCES `teacher` (`id`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
KEY `index_lab_inventory_key` (`inventory_key`),
CONSTRAINT `c_fk_lab_labtype_id` FOREIGN KEY (`labtype_id`) REFERENCES `labtype` (`id`) ON UPDATE CASCADE,
CONSTRAINT `c_fk_lab_responsible_id` FOREIGN KEY (`responsible_id`) REFERENCES `teacher` (`id`) ON DELETE SET NULL ON UPDATE CASCADE,
CONSTRAINT `c_fk_lab_school_id` FOREIGN KEY (`school_id`) REFERENCES `school` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
--
......
......@@ -116,11 +116,11 @@
if (!labId) {
this.$el.find('.modal-footer button.remove')
.prop('disabled', true)
.hide();
.addClass('hidden');
} else {
this.$el.find('.modal-fotter button.remove')
this.$el.find('.modal-footer button.remove')
.prop('disabled', false)
.show();
.removeClass('hidden');
}
this.lab = labId && this.model.get(labId) || null;