Completamento Checklists

This commit is contained in:
Thomas Zilio 2019-07-30 16:50:10 +02:00
parent 4d3ef8cc27
commit 48149dd6d6
32 changed files with 693 additions and 501 deletions

View File

@ -108,6 +108,17 @@ elseif (filter('op') == 'add_nota') {
flash()->info(tr('Nota interna aggiunta correttamente!'));
}
// Rimozione data di notifica dalla nota interna
elseif (filter('op') == 'notification_nota') {
$id_nota = post('id_nota');
$nota = Note::find($id_nota);
$nota->notification_date = null;
$nota->save();
flash()->info(tr('Data di notifica rimossa dalla nota interna!'));
}
// Rimozione nota interna
elseif (filter('op') == 'delete_nota') {
$id_nota = post('id_nota');
@ -122,10 +133,14 @@ elseif (filter('op') == 'delete_nota') {
elseif (filter('op') == 'clone_checklist') {
$content = post('content');
$checklist_id = post('checklist');
$assigned_user = User::find(post('assigned_user'));
$users = post('assigned_users');
$users = array_clean($users);
$group_id = post('group_id');
$checklist = Checklist::find($checklist_id);
$checklist->copia($user, $assigned_user, $id_record);
$checklist->copia($user, $id_record, $users, $group_id);
}
// Aggiunta check alla checklist
@ -133,9 +148,13 @@ elseif (filter('op') == 'add_check') {
$content = post('content');
$parent_id = post('parent') ?: null;
$assigned_user = User::find(post('assigned_user'));
$users = post('assigned_users');
$users = array_clean($users);
$check = Check::build($user, $structure, $id_record, $content, $assigned_user, $parent_id);
$group_id = post('group_id');
$check = Check::build($user, $structure, $id_record, $content, $parent_id);
$check->setAccess($users, $group_id);
}
// Rimozione di un check della checklist
@ -143,8 +162,10 @@ elseif (filter('op') == 'delete_check') {
$check_id = post('check_id');
$check = Check::find($check_id);
if (!empty($check)) {
if (!empty($check) && $check->user->id == $user->id) {
$check->delete();
} else {
flash()->error(tr('Impossibile eliminare il check!'));
}
}
@ -153,8 +174,21 @@ elseif (filter('op') == 'toggle_check') {
$check_id = post('check_id');
$check = Check::find($check_id);
if (!empty($check)) {
if (!empty($check) && $check->assignedUsers->pluck('id')->search($user->id) !== false) {
$check->toggleCheck();
} else {
flash()->error(tr('Impossibile cambiare lo stato del check!'));
}
}
// Gestione ordine per le checklist
elseif (filter('op') == 'sort_checks') {
$ids = explode(',', $_POST['order']);
$order = 0;
foreach ($ids as $id) {
$dbo->query('UPDATE `zz_checks` SET `order` = '.prepare($order).' WHERE id = '.prepare($id));
++$order;
}
}

View File

@ -55,7 +55,7 @@ switch (get('op')) {
break;
case 'checklists':
echo '{( "name": "checklists", "id_module": "'.$id_module.'", "id_record": "'.$id_record.'", "id_plugin": "'.$id_plugin.'" )}';
include DOCROOT.'/plugins/checks.php';
break;

View File

@ -851,39 +851,6 @@ input.small-width {
font-weight: bold;
}
/* Checklist */
ul.checklist {
list-style-type: none;
margin: 0;
padding: 0;
}
ul.checklist li {
cursor: pointer;
position: relative;
padding: 12px 8px 12px 10px;
font-size: 18px;
transition: 0.2s;
/* make the list items unselectable */
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
ul.checklist li:hover {
background: #ddd;
}
ul.checklist li.checked {
background: #eee;
}
ul.checklist li.checked > .check-text {
text-decoration: line-through;
}
.component-loader {
position: absolute;
z-index: 20;
@ -898,3 +865,9 @@ ul.checklist li.checked > .check-text {
top: 50%;
color: #333;
}
/* Checklist */
.todo-list ul {
list-style: none;
margin-left: 11px;
}

View File

@ -68,15 +68,10 @@ function openLink(event, link) {
}
/**
* Funzione per far scrollare la pagina fino a un id + focus e offset
* Funzione per far scrollare la pagina fino a un offset
* @param integer offset
* @param string id
*/
function scrollToAndFocus(offset, id) {
if (id) {
offset += $('#' + id).offset().top;
}
function scrollToOffset(offset) {
$('html,body').animate({
scrollTop: offset
}, 'slow');
@ -420,32 +415,7 @@ function submitAjax(form, data, callback, errorCallback) {
$("#main_loading").fadeOut();
// Visualizzazione messaggi
$.ajax({
url: globals.rootdir + '/ajax.php',
type: 'get',
data: {
op: 'flash',
},
success: function (flash) {
messages = JSON.parse(flash);
info = messages.info ? messages.info : {};
Object.keys(info).forEach(function (element) {
toastr["success"](info[element]);
});
warning = messages.warning ? messages.warning : {};
Object.keys(warning).forEach(function (element) {
toastr["warning"](warning[element]);
});
error = messages.error ? messages.error : {};
Object.keys(error).forEach(function (element) {
toastr["error"](error[element]);
});
}
});
renderMessages();
},
error: function (data) {
$("#main_loading").fadeOut();
@ -460,6 +430,34 @@ function submitAjax(form, data, callback, errorCallback) {
return valid;
}
function renderMessages() {
// Visualizzazione messaggi
$.ajax({
url: globals.rootdir + '/ajax.php',
type: 'get',
data: {
op: 'flash',
},
success: function (flash) {
messages = JSON.parse(flash);
info = messages.info ? messages.info : {};
Object.keys(info).forEach(function (element) {
toastr["success"](info[element]);
});
warning = messages.warning ? messages.warning : {};
Object.keys(warning).forEach(function (element) {
toastr["warning"](warning[element]);
});
error = messages.error ? messages.error : {};
Object.keys(error).forEach(function (element) {
toastr["error"](error[element]);
});
}
});
}
function removeHash() {
history.replaceState(null, null, ' ');
}

View File

@ -17,3 +17,10 @@ String.prototype.toEnglish = function () {
Number.prototype.toLocale = function () {
return numeral(this).format();
};
jQuery.fn.scrollTo = function(elem, speed) {
$(this).animate({
scrollTop: $(this).scrollTop() - $(this).offset().top + $(elem).offset().top
}, speed == undefined ? 1000 : speed);
return this;
};

View File

@ -28,7 +28,7 @@ $(document).ready(function () {
// Riporto l'utente allo scroll precedente
if (sessionStorage['scrollTop_' + globals.id_module + '_' + globals.id_record] != undefined) {
setTimeout(function () {
scrollToAndFocus(sessionStorage['scrollTop_' + globals.id_module + '_' + globals.id_record]);
scrollToOffset(sessionStorage['scrollTop_' + globals.id_module + '_' + globals.id_record]);
}, 1);
}
}

View File

@ -93,10 +93,23 @@ if (empty($record) || !$has_access) {
}
// Tab per le note interne
if ($structure->permission != '-') {
if ($structure->permission != '-' && $structure->use_notes) {
$notes = $structure->recordNotes($id_record);
echo '
<li class="bg-info">
<a data-toggle="tab" href="#tab_note" id="link-tab_note">'.tr('Note interne').'</a>
<a data-toggle="tab" href="#tab_note" id="link-tab_note">
'.tr('Note interne').'
<span class="badge">'.($notes->count() ?: '').'</span>
</a>
</li>';
}
// Tab per le checklist
if ($structure->permission != '-' && $structure->use_checklists) {
echo '
<li class="bg-success">
<a data-toggle="tab" href="#tab_checks" id="link-tab_checks">'.tr('Checklist').'</a>
</li>';
}
@ -273,97 +286,21 @@ if (empty($record) || !$has_access) {
});
</script>';
if ($structure->permission != '-') {
if ($structure->permission != '-' && $structure->use_notes) {
echo '
<div id="tab_note" class="tab-pane">';
$note = $structure->notes($id_record);
if (!empty($note)) {
echo '
<div class="box box-warning direct-chat direct-chat-warning">
<div class="box-header with-border">
<h3 class="box-title">'.tr('Note interne').'</h3>
</div>
include DOCROOT.'/plugins/notes.php';
<div class="box-body">
<div class="direct-chat-messages" style="height: 50vh">';
echo '
</div>';
}
foreach ($note as $nota) {
$utente = $nota->user;
$nome = $utente->anagrafica ? $utente->anagrafica->ragione_sociale.' ('.$utente->username.')' : $utente->username;
$photo = $utente->photo;
if ($structure->permission != '-' && $structure->use_checklists) {
echo '
<div id="tab_checks" class="tab-pane">';
echo '
<div class="direct-chat-msg '.($utente->id == $user->id ? 'right' : '').'" id="nota_'.$nota->id.'">
<div class="direct-chat-info clearfix">
<span class="direct-chat-name pull-left">'.$nome.'</span>
<span class="direct-chat-timestamp pull-right">
'.timestampFormat($nota->created_at).'
</span>
</div>';
if ($photo) {
echo '
<img class="direct-chat-img" src="'.$photo.'">';
} else {
echo '
<i class="fa fa-user-circle-o direct-chat-img fa-3x" alt="'.tr('OpenSTAManager').'"></i>';
}
echo '
<div class="direct-chat-text">
<div class="pull-right">';
if (!empty($nota->notification_date)) {
echo '
<span class="label label-default tip" title="'.tr('Data di notifica').'" style="margin-right: 5px">
<i class="fa fa-bell"></i> '.dateFormat($nota->notification_date).'
</span>';
}
if ($user->is_admin || $utente->id == $user->id) {
echo '
<button type="button" class="btn btn-danger btn-xs ask" data-op="delete_nota" data-id_nota="'.$nota->id.'" data-msg="'.tr('Rimuovere questa nota?').'" data-backto="record-edit">
<i class="fa fa-trash-o"></i>
</button>';
}
echo '
</div>
'.$nota->content.'
</div>
</div>';
}
echo '
</div>
</div>
</div>';
} else {
echo '
<p>'.tr('Non sono presenti note interne').'</p>';
}
if ($structure->permission == 'rw') {
echo '
<form action="" method="post">
<input type="hidden" name="op" value="add_nota">
<input type="hidden" name="backto" value="record-edit">
{[ "type": "date", "label": "'.tr('Data di notifica').'", "name": "data_notifica" ]}
{[ "type": "ckeditor", "label": "'.tr('Nuova nota').'", "name": "contenuto", "required": 1]}
<!-- PULSANTI -->
<div class="row">
<div class="col-md-12 text-right">
<button type="sumbit" class="btn btn-primary">
<i class="fa fa-plus"></i> '.tr('Aggiungi').'
</button>
</div>
</div>
</form>';
}
include DOCROOT.'/plugins/checks.php';
echo '
</div>';
@ -438,7 +375,8 @@ if (empty($record) || !$has_access) {
</li>';
}
echo ' </ul>';
echo '
</ul>';
} else {
echo '
<div class="alert alert-info">

View File

@ -58,7 +58,6 @@ if (!isset($options['edit_articolo']) || !empty($options['edit_articolo'])) {
echo '
<script>
$(document).ready(function () {
console.log($(this).closest("modal"));
$("#idarticolo").on("change", function(){
// Autoimpostazione dei valori relativi
if ($(this).val()) {

View File

@ -52,5 +52,16 @@ switch (post('op')) {
flash()->info(tr('Riga della checklist eliminata!'));
break;
case 'update_position':
$ids = explode(',', $_POST['order']);
$order = 0;
foreach ($ids as $id) {
$dbo->query('UPDATE `zz_checklist_items` SET `order` = '.prepare($order).' WHERE id = '.prepare($id));
++$order;
}
break;
}

View File

@ -7,26 +7,17 @@ echo '
<input type="hidden" name="op" value="add">
<input type="hidden" name="backto" value="record-edit">
<!-- DATI -->
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">'.tr('Dati').'</h3>
<div class="row">
<div class="col-md-6">
{[ "type": "text", "label": "'.tr('Nome').'", "name": "name", "value": "$name$", "required": 1 ]}
</div>
<div class="panel-body">
<div class="row">
<div class="col-md-6">
{[ "type": "text", "label": "'.tr('Nome').'", "name": "name", "value": "$name$", "required": 1 ]}
</div>
<div class="col-md-3">
{[ "type": "select", "label": "'.tr('Modulo del template').'", "name": "module", "values": "query=SELECT id, title AS descrizione FROM zz_modules WHERE enabled = 1", "value": "'.$record['id_module'].'", "disabled": "'.!empty($record['id_plugin']).'" ]}
</div>
<div class="col-md-3">
{[ "type": "select", "label": "'.tr('Plugin del template').'", "name": "plugin", "values": "query=SELECT id, title AS descrizione FROM zz_plugins WHERE enabled = 1", "value": "'.$record['id_plugin'].'", "disabled": "'.!empty($record['id_module']).'" ]}
</div>
</div>
<div class="col-md-3">
{[ "type": "select", "label": "'.tr('Modulo del template').'", "name": "module", "values": "query=SELECT id, title AS descrizione FROM zz_modules WHERE enabled = 1", "value": "'.$record['id_module'].'", "disabled": "'.!empty($record['id_plugin']).'" ]}
</div>
<div class="col-md-3">
{[ "type": "select", "label": "'.tr('Plugin del template').'", "name": "plugin", "values": "query=SELECT id, title AS descrizione FROM zz_plugins WHERE enabled = 1", "value": "'.$record['id_plugin'].'", "disabled": "'.!empty($record['id_module']).'" ]}
</div>
</div>

View File

@ -4,7 +4,7 @@ include_once __DIR__.'/../../../core.php';
$manager_id = filter('manager_id');
$checks = $structure->checks($id_record);
$checks = $structure->recordChecks($id_record);
$list = [];
foreach ($checks as $check) {
$list[] = [
@ -16,18 +16,22 @@ foreach ($checks as $check) {
echo '
<form action="" method="post" id="check-form">
<div class="row">
<div class="col-md-12">
<div class="col-md-9">
{[ "type": "text", "label": "'.tr('Contenuto').'", "name": "content", "required": 1 ]}
</div>
<div class="col-md-3">
{[ "type": "select", "label": "'.tr('Genitore').'", "name": "parent", "values": '.json_encode($list).' ]}
</div>
</div>
<div class="row">
<div class="col-md-6">
{[ "type": "select", "label": "'.tr('Genitore').'", "name": "parent", "values": '.json_encode($list).', "required": 1 ]}
<div class="col-md-6">
{[ "type": "select", "label": "'.tr('Utente').'", "name": "assigned_users", "ajax-source": "utenti", "multiple": 1 ]}
</div>
<div class="col-md-6">
{[ "type": "select", "label": "'.tr('Utente').'", "name": "assigned_user", "ajax-source": "utenti", "required": 1 ]}
<div class="col-md-6">
{[ "type": "select", "label": "'.tr('Gruppo').'", "name": "group_id", "values": "query=SELECT id, nome AS text FROM zz_groups" ]}
</div>
</div>
@ -52,18 +56,32 @@ $(document).ready(function() {
});
$("#parent").change(function(){
if ($(this).val()) {
$("#assigned_user").val("").attr("disabled", true).attr("required", false);
if ($(this).selectData()) {
$("#assigned_users").val("").attr("disabled", true).attr("required", false);
$("#group_id").val("").attr("disabled", true).attr("required", false);
} else {
$("#assigned_user").val("").attr("disabled", false).attr("required", true);
$("#assigned_users").val("").attr("disabled", false).attr("required", true);
$("#group_id").val("").attr("disabled", false).attr("required", true);
}
});
$("#assigned_user").change(function(){
if ($(this).val()) {
$("#assigned_users").change(function(){
if ($(this).selectData()) {
$("#parent").val("").attr("disabled", true).attr("required", false);
$("#group_id").val("").attr("disabled", true).attr("required", false);
} else {
$("#parent").val("").attr("disabled", false).attr("required", true);
$("#group_id").val("").attr("disabled", false).attr("required", true);
}
});
$("#group_id").change(function(){
if ($(this).selectData()) {
$("#parent").val("").attr("disabled", true).attr("required", false);
$("#assigned_users").val("").attr("disabled", true).attr("required", false);
} else {
$("#parent").val("").attr("disabled", false).attr("required", true);
$("#assigned_users").val("").attr("disabled", false).attr("required", true);
}
});
});
@ -95,7 +113,8 @@ function addCheck(btn) {
checklist.addCheck({
content: $form.find("#content").val(),
parent: $form.find("#parent").val(),
assigned_user: $form.find("#assigned_user").val(),
assigned_users: $form.find("#assigned_users").val(),
group_id: $form.find("#group_id").val(),
});
$form.closest(".modal").modal("hide");

View File

@ -4,7 +4,7 @@ include_once __DIR__.'/../../../core.php';
$manager_id = filter('manager_id');
$checklists = $structure->checklists();
$checklists = $structure->checklists()->orderBy('created_at')->get();
$list = [];
foreach ($checklists as $checklist) {
$list[] = [
@ -16,12 +16,18 @@ foreach ($checklists as $checklist) {
echo '
<form action="" method="post" id="check-form">
<div class="row">
<div class="col-md-6">
{[ "type": "select", "label": "'.tr('Checklist').'", "name": "checklist", "values": '.json_encode($list).', "required": 1 ]}
<div class="col-md-12">
{[ "type": "select", "label": "'.tr('Checklist').'", "name": "checklist", "values": '.json_encode($list).' ]}
</div>
</div>
<div class="row">
<div class="col-md-6">
{[ "type": "select", "label": "'.tr('Utente').'", "name": "assigned_users", "ajax-source": "utenti", "multiple": 1 ]}
</div>
<div class="col-md-6">
{[ "type": "select", "label": "'.tr('Utente').'", "name": "assigned_user", "ajax-source": "utenti", "required": 1 ]}
<div class="col-md-6">
{[ "type": "select", "label": "'.tr('Gruppo').'", "name": "group_id", "values": "query=SELECT id, nome AS text FROM zz_groups" ]}
</div>
</div>
@ -44,6 +50,22 @@ $(document).ready(function() {
$("#check-add").click(function(event){
addChecklist(this);
});
$("#assigned_users").change(function(){
if ($(this).selectData()) {
$("#group_id").val("").attr("disabled", true).attr("required", false);
} else {
$("#group_id").val("").attr("disabled", false).attr("required", true);
}
});
$("#group_id").change(function(){
if ($(this).selectData()) {
$("#assigned_users").val("").attr("disabled", true).attr("required", false);
} else {
$("#assigned_users").val("").attr("disabled", false).attr("required", true);
}
});
});
function addChecklist(btn) {

View File

@ -2,8 +2,6 @@
include_once __DIR__.'/../../core.php';
use Modules\Checklists\HTMLBuilder\ChecklistManager;
echo '
<form action="" method="post" id="edit-form">
<input type="hidden" name="op" value="update">
@ -91,11 +89,11 @@ echo '
</form>
<hr>
<ul class="checklist">';
<ul class="todo-list checklist">';
$checks = $record->mainChecks();
foreach ($checks as $check) {
echo ChecklistManager::renderChecklist($check);
echo renderChecklist($check);
}
echo '
@ -106,6 +104,26 @@ echo '
echo '
<script>
$(document).ready(function() {
$(".checklist").sortable({
placeholder: "sort-highlight",
handle: ".handle",
forcePlaceholderSize: true,
zIndex: 999999,
update: function(event, ui) {
var order = [];
$(".checklist > li").each( function(){
order.push($(this).data("id"));
});
$.post(globals.rootdir + "/actions.php", {
id_module: globals.id_module,
id_record: globals.id_record,
op: "update_position",
order: order.join(","),
});
}
});
$(".check-delete").click(function(event){
var li = $(this).closest("li");
var id = li.attr("id").replace("check_", "");

View File

@ -32,18 +32,13 @@ class Checklist {
data: data,
success: function() {
$this.reload();
renderMessages();
}
});
}
deleteCheck(id, user_id) {
var check = this.findCheck(id);
if (check.user_id != user_id && check.assigned_user_id != user_id) {
return false;
}
check.icon.removeClass("fa-check-square-o").addClass("fa-refresh fa-spin bg-danger").show();
deleteCheck(id) {
this.request({
op: "delete_check",
check_id: id,
@ -52,14 +47,7 @@ class Checklist {
return true;
}
toggleCheck(id, user_id) {
var check = this.findCheck(id);
if (check.assigned_user_id != user_id) {
return false;
}
check.icon.removeClass("fa-square-o fa-check-square-o ").addClass("fa-refresh fa-spin").show();
toggleCheck(id) {
this.request({
op: "toggle_check",
check_id: id,
@ -73,12 +61,10 @@ class Checklist {
return {
item: li,
icon: li.find(".check-icon"),
date: li.find(".check-date"),
text: li.find(".check-text"),
children: li.find(".check-children"),
user_id: li.data('user_id'),
assigned_user_id: li.data('assigned_user_id'),
input: li.find("input"),
info: li.find(".badge"),
text: li.find(".text"),
children: li.find("ul"),
};
}

View File

@ -0,0 +1,40 @@
<?php
function renderChecklist($check, $level = 0)
{
$user = auth()->getUser();
$enabled = $check->assignedUsers->pluck('id')->search($user->id) !== false;
$result = '
<li id="check_'.$check->id.'" class="check-item'.(!empty($check->checked_at) ? ' done' : '').'" '.(!$enabled ? 'style="opacity: 0.4"' : '').' data-id="'.$check->id.'">
<input type="checkbox" value="'.(!empty($check->checked_at) ? '1' : '0').'" '.(!empty($check->checked_at) ? 'checked' : '').'>
<span class="text">'.$check->content.'</span>
<span class="badge">'.(!empty($check->checked_at) ? timestampFormat($check->checked_at).' - '.$check->user->username : '').'</span>';
if ($level == 0) {
$result .= '
<span class="handle pull-right">
<i class="fa fa-ellipsis-v"></i>
<i class="fa fa-ellipsis-v"></i>
</span>';
}
$result .= '
<div class="tools">
<i class="fa fa-trash-o check-delete"></i>
</div>
<ul class="todo-list">';
$children = $check->children;
foreach ($children as $child) {
$result .= renderChecklist($child, $level + 1);
}
$result .= '
</ul>
</li>';
return $result;
}

View File

@ -3,6 +3,7 @@
namespace Modules\Checklists;
use Common\Model;
use Models\Group;
use Models\Module;
use Models\Plugin;
use Models\User;
@ -20,7 +21,6 @@ class Check extends Model
* Crea un nuovo elemento della checklist.
*
* @param User $user
* @param User $assigned_user
* @param ChecklistTrait $structure
* @param int $id_record
* @param string $content
@ -28,19 +28,13 @@ class Check extends Model
*
* @return self
*/
public static function build(User $user, $structure, $id_record, $content, User $assigned_user = null, $parent_id = null)
public static function build(User $user, $structure, $id_record, $content, $parent_id = null)
{
$model = parent::build();
$model->user()->associate($user);
$model->id_parent = $parent_id;
if (empty($parent_id)) {
$model->assignedUser()->associate($assigned_user);
} else {
$model->assignedUser()->associate($model->parent->assignedUser);
}
if ($structure instanceof Module) {
$model->module()->associate($structure);
} elseif ($structure instanceof Plugin) {
@ -50,6 +44,9 @@ class Check extends Model
$model->id_record = $id_record;
$model->content = $content;
// Ordinamento temporaneo alla creazione
$model->order = 99;
$model->save();
return $model;
@ -71,6 +68,28 @@ class Check extends Model
}
}
public function setAccess($users, $group_id)
{
if (!empty($this->id_parent)) {
$users = $this->parent->assignedUsers->pluck('id')->toArray();
$this->assignedUsers()->sync($users);
return;
}
if (empty($users)) {
if (!empty($group_id)) {
$group = Group::find($group_id);
$users = $group->users->pluck('id')->toArray();
} else {
$users = User::all()->pluck('id')->toArray();
}
}
$this->assignedUsers()->sync($users);
}
/*
* Rimozione ricorsiva gestita da MySQL.
public function delete()
@ -91,12 +110,12 @@ class Check extends Model
public function user()
{
return $this->belongsTo(User::class, 'id_utente');
return $this->belongsTo(User::class, 'created_by');
}
public function assignedUser()
public function assignedUsers()
{
return $this->belongsTo(User::class, 'id_utente_assegnato');
return $this->belongsToMany(User::class, 'zz_check_user', 'id_check', 'id_utente');
}
public function plugin()

View File

@ -30,10 +30,10 @@ class Checklist extends Model
public function mainChecks()
{
return $this->checks()->whereNull('id_parent')->orderBy('created_at')->get();
return $this->checks()->whereNull('id_parent')->orderBy('order')->get();
}
public function copia(User $user, User $assigned_user, $id_record)
public function copia(User $user, $id_record, $users, $group_id)
{
$structure = $this->plugin ?: $this->module;
@ -44,7 +44,9 @@ class Checklist extends Model
$child = $checks->shift();
$id_parent = $child->id_parent ? $relations[$child->id_parent] : null;
$check = Check::build($user, $structure, $id_record, $child->content, $assigned_user, $id_parent);
$check = Check::build($user, $structure, $id_record, $child->content, $id_parent);
$check->setAccess($users, $group_id);
$relations[$child->id] = $check->id;
$checks = $checks->merge($child->children);

View File

@ -29,6 +29,8 @@ class ChecklistItem extends Model
$model->id_parent = $id_parent;
$model->content = $contenuto;
$model->findOrder();
$model->save();
return $model;
@ -40,4 +42,9 @@ class ChecklistItem extends Model
{
return $this->belongsTo(Checklist::class, 'id_checklist');
}
protected function findOrder()
{
$this->order = orderValue($this->table, 'id_checklist', $this->id_checklist);
}
}

View File

@ -1,181 +0,0 @@
<?php
namespace Modules\Checklists\HTMLBuilder;
use HTMLBuilder\Manager\ManagerInterface;
use Models\User;
use Modules;
use Plugins;
/**
* Gestione delle checklist.
*
* @since 2.4.11
*/
class ChecklistManager implements ManagerInterface
{
/**
* Gestione "checklists".
* Esempio: {( "name": "checklists", "id_module": "2", "id_record": "1", "readonly": "false" )}.
*
* @param array $options
*
* @return string
*/
public function manage($options)
{
$module = Modules::get('Checklists');
$structure = Plugins::get($options['id_plugin']) ?: Modules::get($options['id_module']);
$utente = \Auth::user();
// ID del form
$manager_id = 'checklist_'.$options['id_module'].'_'.$options['id_plugin'];
$result = '
<div class="panel panel-primary" id="'.$manager_id.'" style="position:relative">
<div class="panel-heading">
<h3 class="panel-title">'.tr('Checklist').'</h3>
</div>
<div class="panel-body" style="position:relative">
<div id="loading_'.$manager_id.'" class="text-center hide component-loader">
<div>
<i class="fa fa-refresh fa-spin fa-3x fa-fw"></i>
<span class="sr-only">'.tr('Caricamento...').'</span>
</div>
</div>';
// Form per la creazione di una nuova checklist
if (!$options['readonly']) {
$result .= '
<div class="row">
<div class="col-md-12">
<a class="btn btn-sm btn-primary" data-href="'.$module->fileurl('components/add-check.php').'?id_module='.$options['id_module'].'&id_record='.$options['id_record'].'&id_plugin='.$options['id_plugin'].'&manager_id='.$manager_id.'" data-toggle="tooltip" data-title="'.tr('Aggiungi check').'">
<i class="fa fa-plus"></i> '.tr('Check').'
</a>
<a class="btn btn-sm btn-primary" data-href="'.$module->fileurl('components/add-checklist.php').'?id_module='.$options['id_module'].'&id_record='.$options['id_record'].'&id_plugin='.$options['id_plugin'].'&manager_id='.$manager_id.'" data-toggle="tooltip" data-title="'.tr('Aggiungi check').'">
<i class="fa fa-plus"></i> '.tr('Checklist').'
</a>
</div>
</div>
<div class="clearfix"></div>
<br>';
}
$checks = $structure->mainChecks($options['id_record']);
$users = $checks->groupBy('id_utente_assegnato');
$result .= '
<div class="row">';
foreach ($users as $user_id => $checks) {
$user = User::find($user_id);
$result .= '
<div class="col-md-6" '.($utente->id != $user_id ? 'style="opacity: 0.5"' : '').'>
<div class="box box-info">
<div class="box-header">
<h3 class="box-title">'.$user->nome_completo.'</h3>
</div>
<div class="box-body">
<ul class="checklist">';
foreach ($checks as $check) {
$result .= self::renderChecklist($check);
}
$result .= '
</ul>
</div>
</div>
</div>';
}
$result .= '
</div>
</div>
</div>';
$result .= '
<script>$(document).ready(init)</script>
<script type="module">
import Checklist from "./modules/checklists/js/checklist.js";
var checklists = checklists ? checklists : {};
$(document).ready(function() {
checklists["'.$manager_id.'"] = new Checklist({
id_module: "'.$options['id_module'].'",
id_plugin: "'.$options['id_plugin'].'",
id_record: "'.$options['id_record'].'",
}, "'.$manager_id.'");
$(".check-item").click(function(event){
var id = $(this).attr("id").replace("check_", "");
var result = checklists["'.$manager_id.'"].toggleCheck(id, '.$utente->id.');
if (!result){
swal("'.tr('Errore').'", "'.tr('La tua utenza non corrisponde a quella assegnata al check').'", "error");
}
});
$(".check-delete").click(function(event){
var li = $(this).closest("li");
var id = li.attr("id").replace("check_", "");
var result = checklists["'.$manager_id.'"].deleteCheck(id, '.$utente->id.');
if (!result){
swal("'.tr('Errore').'", "'.tr('La tua utenza non possiede i permessi di modificare questo check').'", "error");
}
event.stopPropagation();
});
});
function deleteCheck(id) {
swal({
title: "'.tr("Rimuovere l'elemento della checklist?").'",
html: "'.tr('Tutti gli elementi figli saranno rimossi di conseguenza. Continuare?').'",
showCancelButton: true,
confirmButtonText: "'.tr('Procedi').'",
type: "error",
}).then(function (result) {
checklists["'.$manager_id.'"].toggleCheck(id);
});
}
</script>';
return $result;
}
public static function renderChecklist($check, $level = 0)
{
$result = '
<li id="check_'.$check->id.'" class="check-item'.(!empty($check->checked_at) ? ' checked' : '').'" data-user_id="'.$check->id_utente.'" data-assigned_user_id="'.$check->id_utente_assegnato.'">
'.str_repeat('&nbsp;', $level * 8).'
<i class="check-icon fa '.(!empty($check->checked_at) ? 'fa-check-square-o' : 'fa-square-o').'"></i>
<span class="check-text">'.$check->content.'</span>
<div class="pull-right">
<span class="badge check-date">'.timestampFormat($check->checked_at).'</span>
<i class="fa fa-close check-delete"></i>
</div>
</li>
<ul class="checklist" class="check-children">';
$children = $check->children;
foreach ($children as $child) {
$result .= self::renderChecklist($child, $level + 1);
}
$result .= '
</ul>';
return $result;
}
}

View File

@ -7,18 +7,23 @@ use Modules\Checklists\Checklist;
trait ChecklistTrait
{
public function checks($id_record)
public function checks()
{
return $this->hasMany(Check::class, $this->component_identifier)->where('id_record', $id_record)->orderBy('created_at')->get();
return $this->hasMany(Check::class, $this->component_identifier);
}
public function recordChecks($id_record)
{
return $this->checks()->where('id_record', $id_record)->orderBy('order')->get();
}
public function mainChecks($id_record)
{
return $this->hasMany(Check::class, $this->component_identifier)->where('id_record', $id_record)->whereNull('id_parent')->orderBy('id_utente_assegnato', 'created_at')->get();
return $this->checks()->where('id_record', $id_record)->whereNull('id_parent')->orderBy('order')->get();
}
public function checklists()
{
return $this->hasMany(Checklist::class, $this->component_identifier)->orderBy('created_at')->get();
return $this->hasMany(Checklist::class, $this->component_identifier);
}
}

View File

@ -0,0 +1,68 @@
<?php
include_once __DIR__.'/../../../core.php';
use Carbon\Carbon;
use Models\Module;
if (!empty($is_title_request)) {
echo tr('Notifiche interne');
return;
}
$notes = collect();
$moduli = Module::getAll()->where('permission', '<>', '-');
foreach ($moduli as $modulo) {
$note = $modulo->notes()->where('notification_date', '>=', date('Y-m-d'))->get();
$notes = $notes->merge($note);
}
if (!empty($is_number_request)) {
echo $notes->count();
return;
}
if (empty($notes)) {
echo '
<p>'.tr('Non ci sono note da notificare').'.</p>';
return;
}
$moduli = $notes->groupBy('id_module')->sortBy('notification_date');
foreach ($moduli as $module_id => $note) {
$modulo = Module::get($module_id);
echo '
<h4>'.$modulo->title.'</h4>
<table class="table table-hover">
<tr>
<th width="5%" >'.tr('Record').'</th>
<th>'.tr('Contenuto').'</th>
<th width="20%" class="text-center">'.tr('Data di notifica').'</th>
</tr>';
foreach ($note as $nota) {
echo '
<tr>
<td>'.$nota->id_record.'</td>
<td>
<span class="pull-right">'.Modules::link($module_id, $nota->id_record, null, null, null, true, 'tab_note').'</span>
'.$nota->content.'
<small>'.$nota->user->nome_completo.'</small>
</td>
<td class="text-center">
'.$nota->notification_date.'
('.Carbon::parse($nota->notification_date)->diffForHumans().')
</td>
</tr>';
}
echo '
</table>';
}

View File

@ -9,7 +9,7 @@ if (!empty($rs)) {
<table class="table table-hover">
<tr>
<th width="50%">'.tr('Attività').'</th>
<th width="15%">'.tr('Data richiesta').'</th>
<th width="15%" class="text-center">'.tr('Data richiesta').'</th>
</tr>';
foreach ($rs as $r) {

119
plugins/checks.php Normal file
View File

@ -0,0 +1,119 @@
<?php
include_once __DIR__.'/../core.php';
$checklist_module = Modules::get('Checklists');
$checks_id = 'checklist_'.$id_module.'_'.$id_plugin;
echo '
<div class="box box-primary" id="'.$checks_id.'">
<div class="box-header">
<h3 class="box-title">'.tr('Checklist').'</h3>
</div>
<div class="box-body" style="position:relative">
<div id="loading_'.$checks_id.'" class="text-center hide component-loader">
<div>
<i class="fa fa-refresh fa-spin fa-3x fa-fw"></i>
<span class="sr-only">'.tr('Caricamento...').'</span>
</div>
</div>';
// Form per la creazione di una nuova checklist
if ($structure->permission == 'rw') {
echo '
<div class="row">
<div class="col-md-12">
<a class="btn btn-sm btn-primary" data-href="'.$checklist_module->fileurl('components/add-check.php').'?id_module='.$id_module.'&id_record='.$id_record.'&id_plugin='.$id_plugin.'&manager_id='.$checks_id.'" data-toggle="tooltip" data-title="'.tr('Aggiungi check').'">
<i class="fa fa-plus"></i> '.tr('Check').'
</a>
<a class="btn btn-sm btn-primary" data-href="'.$checklist_module->fileurl('components/add-checklist.php').'?id_module='.$id_module.'&id_record='.$id_record.'&id_plugin='.$id_plugin.'&manager_id='.$checks_id.'" data-toggle="tooltip" data-title="'.tr('Aggiungi check').'">
<i class="fa fa-plus"></i> '.tr('Checklist').'
</a>
</div>
</div>
<div class="clearfix"></div>
<br>';
}
$checks = $structure->mainChecks($id_record);
echo '
<ul class="todo-list checklist">';
foreach ($checks as $check) {
echo renderChecklist($check);
}
echo '
</ul>
</div>
</div>';
echo '
<script>$(document).ready(init)</script>
<script type="module">
import Checklist from "./modules/checklists/js/checklist.js";
var checklists = checklists ? checklists : {};
$(document).ready(function() {
checklists["'.$checks_id.'"] = new Checklist({
id_module: "'.$id_module.'",
id_plugin: "'.$id_plugin.'",
id_record: "'.$id_record.'",
}, "'.$checks_id.'");
$(".checklist").sortable({
placeholder: "sort-highlight",
handle: ".handle",
forcePlaceholderSize: true,
zIndex: 999999,
update: function(event, ui) {
var order = [];
$(".checklist > li").each( function(){
order.push($(this).data("id"));
});
$.post(globals.rootdir + "/actions.php", {
id_module: "'.$id_module.'",
id_plugin: "'.$id_plugin.'",
id_record: "'.$id_record.'",
op: "sort_checks",
order: order.join(","),
});
}
});
$(".checklist").todoList({
onCheck : function () {
var id = $(this).parent().data("id");
checklists["'.$checks_id.'"].toggleCheck(id);
},
onUnCheck: function () {
var id = $(this).parent().data("id");
checklists["'.$checks_id.'"].toggleCheck(id);
}
});
$(".check-delete").click(function(event){
var li = $(this).closest("li");
var id = li.data("id");
swal({
title: "'.tr("Rimuovere l'elemento della checklist?").'",
html: "'.tr('Tutti gli elementi figli saranno rimossi di conseguenza. Continuare?').'",
showCancelButton: true,
confirmButtonText: "'.tr('Procedi').'",
type: "error",
}).then(function (result) {
checklists["'.$checks_id.'"].deleteCheck(id);
});
event.stopPropagation();
});
});
</script>';

93
plugins/notes.php Normal file
View File

@ -0,0 +1,93 @@
<?php
include_once __DIR__.'/../core.php';
if (!empty($notes)) {
echo '
<div class="box box-warning direct-chat direct-chat-warning">
<div class="box-header with-border">
<h3 class="box-title">'.tr('Note interne').'</h3>
</div>
<div class="box-body">
<div class="direct-chat-messages" style="height: 50vh">';
foreach ($notes as $nota) {
$utente = $nota->user;
$photo = $utente->photo;
echo '
<div class="direct-chat-msg '.($utente->id == $user->id ? 'right' : '').'" id="nota_'.$nota->id.'">
<div class="direct-chat-info clearfix">
<span class="direct-chat-name pull-left">'.$utente->nome_completo.'</span>
<span class="direct-chat-timestamp pull-right">
'.timestampFormat($nota->created_at).'
</span>
</div>';
if ($photo) {
echo '
<img class="direct-chat-img" src="'.$photo.'">';
} else {
echo '
<i class="fa fa-user-circle-o direct-chat-img fa-3x" alt="'.tr('OpenSTAManager').'"></i>';
}
echo '
<div class="direct-chat-text">
<div class="pull-right">';
if (!empty($nota->notification_date)) {
echo '
<span class="label label-default tip" title="'.tr('Data di notifica').'" style="margin-right: 5px">
<i class="fa fa-bell"></i> '.dateFormat($nota->notification_date).'
</span>
<button type="button" class="btn btn-info btn-xs ask" data-op="notification_nota" data-id_nota="'.$nota->id.'" data-msg="'.tr('Rimuovere la data di notifica da questa nota?').'" data-backto="record-edit" data-button="'.tr('Rimuovi').'" data-class="btn btn-lg btn-warning">
<i class="fa fa-eye"></i>
</button>';
}
if ($user->is_admin || $utente->id == $user->id) {
echo '
<button type="button" class="btn btn-danger btn-xs ask" data-op="delete_nota" data-id_nota="'.$nota->id.'" data-msg="'.tr('Rimuovere questa nota?').'" data-backto="record-edit">
<i class="fa fa-trash-o"></i>
</button>';
}
echo '
</div>
'.$nota->content.'
</div>
</div>';
}
echo '
</div>
</div>
</div>';
} else {
echo '
<p>'.tr('Non sono presenti note interne').'</p>';
}
if ($structure->permission == 'rw') {
echo '
<form action="" method="post">
<input type="hidden" name="op" value="add_nota">
<input type="hidden" name="backto" value="record-edit">
{[ "type": "date", "label": "'.tr('Data di notifica').'", "name": "data_notifica" ]}
{[ "type": "ckeditor", "label": "'.tr('Nuova nota').'", "name": "contenuto", "required": 1]}
<!-- PULSANTI -->
<div class="row">
<div class="col-md-12 text-right">
<button type="sumbit" class="btn btn-primary">
<i class="fa fa-plus"></i> '.tr('Aggiungi').'
</button>
</div>
</div>
</form>';
}

View File

@ -75,7 +75,6 @@ class HTMLBuilder
protected static $managers = [
'list' => [
'filelist_and_upload' => Manager\FileManager::class,
'checklists' => \Modules\Checklists\HTMLBuilder\ChecklistManager::class,
'button' => Manager\ButtonManager::class,
'csrf' => Manager\CSRFManager::class,
'custom_fields' => Manager\FieldManager::class,

View File

@ -91,11 +91,42 @@ class WidgetManager implements ManagerInterface
}
}
// Generazione del codice HTML
return $this->render($widget, $widget['text'], $value);
}
protected function chart($widget, $number = null)
{
$content = null;
if (!empty($widget['php_include'])) {
$is_title_request = true;
ob_start();
include DOCROOT.'/'.$widget['php_include'];
$content = ob_get_clean();
}
return $this->render($widget, $content, $number);
}
protected function custom($widget)
{
$content = null;
if (!empty($widget['php_include'])) {
$is_number_request = true;
ob_start();
include DOCROOT.'/'.$widget['php_include'];
$content = ob_get_clean();
}
return $this->chart($widget, $content);
}
protected function render($widget, $title, $number = null)
{
$result = '
<button type="button" class="close" onclick="if(confirm(\'Disabilitare questo widget?\')) { $.post( \''.ROOTDIR.'/actions.php?id_module='.self::getModule()->id.'\', { op: \'disable_widget\', id: \''.$widget['id'].'\' }, function(response){ location.reload(); }); };" >
<span aria-hidden="true">&times;</span><span class="sr-only">'.tr('Chiudi').'</span>
</button>';
<button type="button" class="close" onclick="if(confirm(\'Disabilitare questo widget?\')) { $.post( \''.ROOTDIR.'/actions.php?id_module='.self::getModule()->id.'\', { op: \'disable_widget\', id: \''.$widget['id'].'\' }, function(response){ location.reload(); }); };" >
<span aria-hidden="true">&times;</span><span class="sr-only">'.tr('Chiudi').'</span>
</button>';
if (!empty($widget['more_link'])) {
$result .= '
@ -124,21 +155,36 @@ class WidgetManager implements ManagerInterface
}
$result .= '
<div class="info-box">
<span class="info-box-icon" style="background-color:'.$widget['bgcolor'].'">
<i class="'.$widget['icon'].'"></i>
</span>
<div class="info-box-content">
<span class="info-box-text'.(!empty($widget['help']) ? ' tip' : '').'"'.(!empty($widget['help']) ? ' title="'.prepareToField($widget['help']).'" data-position="bottom"' : '').'>
'.$widget['text'].'
<div class="info-box">
<span class="info-box-icon" style="background-color:'.$widget['bgcolor'].'">';
'.(!empty($widget['help']) ? '<i class="fa fa-question-circle-o"></i>' : '').'
</span>
<span class="info-box-number">'.$value.'</span>
</div>
if (!empty($widget['icon'])) {
$result .= '
<i class="'.$widget['icon'].'"></i>';
}
$result .= '
</span>
<div class="info-box-content">
<span class="info-box-text'.(!empty($widget['help']) ? ' tip' : '').'"'.(!empty($widget['help']) ? ' title="'.prepareToField($widget['help']).'" data-position="bottom"' : '').'>
'.$title.'
'.(!empty($widget['help']) ? '<i class="fa fa-question-circle-o"></i>' : '').'
</span>';
if (isset($number)) {
$result .= '
<span class="info-box-number">'.$number.'</span>';
}
$result .= '
</div>';
$result .= '
</div>';
if (!empty($widget['more_link'])) {
$result .= '
</a>';
@ -150,57 +196,6 @@ class WidgetManager implements ManagerInterface
return $result;
}
protected function chart($widget)
{
return $this->custom($widget);
}
protected function custom($widget)
{
$result = '
<button type="button" class="close" onclick="if(confirm(\'Disabilitare questo widget?\')) { $.post( \''.ROOTDIR.'/actions.php?id_module='.self::getModule()->id.'\', { op: \'disable_widget\', id: \''.$widget['id'].'\' }, function(response){ location.reload(); }); };" >
<span aria-hidden="true">&times;</span><span class="sr-only">'.tr('Chiudi').'</span>
</button>';
$result .= '
<div class="info-box">
<span class="info-box-icon" style="background-color:'.$widget['bgcolor'].'">';
if (!empty($widget['icon'])) {
$result .= '
<i class="'.$widget['icon'].'"></i>';
}
$result .= '
</span>
<div class="info-box-content">
<span class="info-box-text">';
if (!empty($widget['php_include'])) {
$result_ob = '';
ob_start();
include DOCROOT.'/'.$widget['php_include'];
$result_ob = ob_get_contents();
ob_end_clean();
$result .= $result_ob;
}
$result .= '
</span>
</div>';
$result .= '
</div>';
return $result;
}
protected function group($options)
{
$query = 'SELECT id FROM zz_widgets WHERE id_module = '.prepare($options['id_module']).' AND (|position|) AND enabled = 1 ORDER BY `order` ASC';

View File

@ -6,8 +6,13 @@ use Models\Note;
trait NoteTrait
{
public function notes($id_record)
public function notes()
{
return $this->hasMany(Note::class, $this->component_identifier)->where('id_record', $id_record)->orderBy('created_at')->get();
return $this->hasMany(Note::class, $this->component_identifier);
}
public function recordNotes($id_record)
{
return $this->notes()->where('id_record', $id_record)->orderBy('created_at')->get();
}
}

View File

@ -61,7 +61,9 @@ trait StoreTrait
->orWhere(self::$name, $identifier)
->first();
self::$collection->push($result);
if (!empty($result)) {
self::$collection->push($result);
}
return $result;
}

View File

@ -80,7 +80,6 @@ class Autofill
$result = '';
$number = $this->getAdditionalNumber();
//dd($this->space, $number);exit();
for ($i = 0; $i < $number; ++$i) {
$result .= '

View File

@ -28,7 +28,7 @@ INSERT INTO `zz_hooks` (`id`, `name`, `class`, `frequency`, `id_module`) VALUES
(NULL, 'Ricevute', 'Modules\\Aggiornamenti\\UpdateHook', '7 day', (SELECT `id` FROM `zz_modules` WHERE `name` = 'Aggiornamenti'));
--
-- Aggiunta nuovi campi per tracciamento sedi
-- Aggiunta nuovi campi per tracciamento sedi
--
ALTER TABLE `mg_movimenti` ADD `idsede_azienda` INT NOT NULL AFTER `idautomezzo`, ADD `idsede_controparte` INT NOT NULL AFTER `idsede_azienda`;
@ -106,7 +106,7 @@ UPDATE `zz_views` SET `query` = 'CONCAT_WS(co_movimenti_modelli.nome, co_movimen
UPDATE `co_movimenti_modelli` SET `nome` = `descrizione` WHERE `nome` = '';
-- Rimuovo le interruzioni di riga per descrizioni vuote
-- Rimuovo le interruzioni di riga per descrizioni vuote
-- UPDATE `in_interventi` SET `descrizione` = REPLACE(`descrizione`, '\n', '') where `descrizione` LIKE '%\n';
-- Aggiunto tabella co_tipi_scadenze
@ -181,6 +181,7 @@ UPDATE `in_interventi_tecnici` INNER JOIN `in_tipiintervento` ON `in_interventi_
ALTER TABLE `in_interventi_tecnici` CHANGE `idtipointervento` `idtipointervento` INT(11) NOT NULL, ADD FOREIGN KEY (`idtipointervento`) REFERENCES `in_tipiintervento`(`idtipointervento`);
UPDATE `in_tariffe` INNER JOIN `in_tipiintervento` ON `in_tariffe`.`idtipointervento` = `in_tipiintervento`.`codice` SET `in_tariffe`.`idtipointervento` = `in_tipiintervento`.`idtipointervento`;
DELETE FROM `in_tariffe` WHERE `idtipointervento` NOT IN (SELECT `idtipointervento` FROM `in_tipiintervento`);
ALTER TABLE `in_tariffe` CHANGE `idtipointervento` `idtipointervento` INT(11) NOT NULL, ADD FOREIGN KEY (`idtipointervento`) REFERENCES `in_tipiintervento`(`idtipointervento`);
-- Ottimizzazione query Fatture

View File

@ -212,19 +212,27 @@ CREATE TABLE IF NOT EXISTS `zz_checks` (
`id_module` int(11),
`id_plugin` int(11),
`id_record` int(11) NOT NULL,
`id_utente` int(11) NOT NULL,
`id_utente_assegnato` int(11) NOT NULL,
`created_by` int(11) NOT NULL,
`checked_at` TIMESTAMP NULL,
`content` TEXT,
`id_parent` int(11),
`order` int(11),
PRIMARY KEY (`id`),
FOREIGN KEY (`id_module`) REFERENCES `zz_modules`(`id`) ON DELETE CASCADE,
FOREIGN KEY (`id_plugin`) REFERENCES `zz_plugins`(`id`) ON DELETE CASCADE,
FOREIGN KEY (`id_utente`) REFERENCES `zz_users`(`id`) ON DELETE CASCADE,
FOREIGN KEY (`id_utente_assegnato`) REFERENCES `zz_users`(`id`) ON DELETE CASCADE,
FOREIGN KEY (`created_by`) REFERENCES `zz_users`(`id`) ON DELETE CASCADE,
FOREIGN KEY (`id_parent`) REFERENCES `zz_checks`(`id`) ON DELETE CASCADE
) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `zz_check_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`id_utente` int(11) NOT NULL,
`id_check` int(11) NOT NULL,
PRIMARY KEY (`id`),
FOREIGN KEY (`id_utente`) REFERENCES `zz_users`(`id`) ON DELETE CASCADE,
FOREIGN KEY (`id_check`) REFERENCES `zz_checks`(`id`) ON DELETE CASCADE
) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `zz_checklists` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255),
@ -240,11 +248,18 @@ CREATE TABLE IF NOT EXISTS `zz_checklist_items` (
`id_checklist` int(11),
`content` TEXT,
`id_parent` int(11),
`order` int(11),
PRIMARY KEY (`id`),
FOREIGN KEY (`id_checklist`) REFERENCES `zz_checklists`(`id`) ON DELETE CASCADE,
FOREIGN KEY (`id_parent`) REFERENCES `zz_checklist_items`(`id`) ON DELETE CASCADE
) ENGINE=InnoDB;
-- Gestione di note e checklists
ALTER TABLE `zz_modules` ADD `use_notes` BOOLEAN DEFAULT FALSE, ADD `use_checklists` BOOLEAN DEFAULT FALSE;
UPDATE `zz_modules` SET `use_notes` = 1 WHERE `name` IN ('Anagrafiche', 'Interventi', 'Preventivi', 'Contratti', 'Fatture di vendita', 'Fatture di acquisto', 'Scadenzario', 'Ordini cliente', 'Ordini fornitore', 'Articoli', 'Ddt di vendita', 'Ddt di acquisto', 'MyImpianti');
UPDATE `zz_modules` SET `use_checklists` = 1 WHERE `name` IN ('Interventi', 'MyImpianti');
-- Modulo per i template delle Checklist
INSERT INTO `zz_modules` (`id`, `name`, `title`, `directory`, `options`, `options2`, `icon`, `version`, `compatibility`, `order`, `parent`, `default`, `enabled`) VALUES (NULL, 'Checklists', 'Checklists', 'checklists', 'SELECT |select| FROM `zz_checklists` WHERE 1=1 HAVING 2=2', '', 'fa fa-check-square-o', '2.4.11', '2.4.11', '1', (SELECT `id` FROM `zz_modules` t WHERE t.`name` = 'Strumenti'), '1', '1');
INSERT INTO `zz_views` (`id_module`, `name`, `query`, `order`, `search`, `slow`, `default`, `visible`) VALUES
@ -264,3 +279,6 @@ UPDATE `zz_prints` SET `options` = '{"pricing": true, "last-page-footer": true}'
UPDATE `zz_prints` SET `options` = '{"pricing": false, "last-page-footer": true}' WHERE `zz_prints`.`name` = 'Preventivo (senza costi)';
UPDATE `zz_prints` SET `options` = '{"pricing": true, "last-page-footer": true}' WHERE `zz_prints`.`name` = 'Contratto';
UPDATE `zz_prints` SET `options` = '{"pricing": false, "last-page-footer": true}' WHERE `zz_prints`.`name` = 'Contratto (senza costi)';
-- Widget per le notifiche delle note interne
INSERT INTO `zz_widgets` (`id`, `name`, `type`, `id_module`, `location`, `class`, `query`, `bgcolor`, `icon`, `print_link`, `more_link`, `more_link_type`, `php_include`, `text`, `enabled`, `order`) VALUES (NULL, 'Note interne', 'custom', (SELECT `id` FROM `zz_modules` WHERE `name` = 'Dashboard'), 'controller_top', 'col-md-12', NULL, '#4ccc4c', 'fa fa-file-text-o ', '', './modules/dashboard/widgets/notifiche.php', 'popup', './modules/dashboard/widgets/notifiche.php', 'Notifiche interne', '1', '1');

View File

@ -81,6 +81,10 @@ return [
'or_tipiordine',
'zz_api_resources',
'zz_currencies',
'zz_checks',
'zz_check_user',
'zz_checklists',
'zz_checklist_items',
'zz_documenti',
'zz_documenti_categorie',
'zz_email_print',
@ -96,6 +100,7 @@ return [
'zz_logs',
'zz_modules',
'zz_operations',
'zz_notes',
'zz_permissions',
'zz_plugins',
'zz_prints',