diff --git a/assets/src/css/style.css b/assets/src/css/style.css
index ce3c6ff71..0f3c87898 100755
--- a/assets/src/css/style.css
+++ b/assets/src/css/style.css
@@ -81,7 +81,8 @@ input[type=file] {
position: fixed;
}
-.ui-autocomplete {
+.autocomplete, .ui-autocomplete {
+ background: white;
z-index: 10000;
min-width: 160px;
padding: 10px;
@@ -94,8 +95,23 @@ input[type=file] {
border-radius: 5px;
}
-.ui-autocomplete-category {
- font-size: 150%;
+.autocomplete .group, .ui-autocomplete-category {
+ font-size: 1.5em;
+ background: inherit;
+}
+
+.autocomplete > div {
+ padding: 5px;
+}
+
+.highlight {
+ background: #FFFF66;
+}
+
+.autocomplete > div:hover:not(.group),
+.autocomplete > div.selected {
+ background: #F5F5F5;
+ cursor: pointer;
}
.ui-autocomplete-scrollable {
@@ -1069,6 +1085,14 @@ div.tip {
background-color: rgba(255, 99, 71, 0.6) !important;
}
-.login-box .img-responsive{
+.login-box .img-responsive {
padding: 18px 0px 4px;
}
+
+.no-selection {
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
diff --git a/assets/src/js/base/datatables-buttons.js b/assets/src/js/base/datatables-buttons.js
index ce35069f5..9838dd939 100644
--- a/assets/src/js/base/datatables-buttons.js
+++ b/assets/src/js/base/datatables-buttons.js
@@ -138,7 +138,7 @@ $(document).ready(function () {
$(this).attr("data-id_records", "");
$(this).data("id_records", "");
} else {
- swal(globals.translations.waiting, globals.translations.waiting_msg, "error");
+ swal(globals.translations.waiting, globals.translations.waitingMessage, "error");
}
});
});
diff --git a/assets/src/js/base/sidebar.js b/assets/src/js/base/sidebar.js
index 906b847aa..c0c292e88 100644
--- a/assets/src/js/base/sidebar.js
+++ b/assets/src/js/base/sidebar.js
@@ -40,21 +40,21 @@ $(document).ready(function () {
}
// Menu ordinabile
- $(".sidebar-menu").sortable({
- cursor: 'move',
+ if (!globals.is_mobile) {
+ sortable(".sidebar-menu", {
+ axis: "y",
+ cursor: "move",
+ dropOnEmpty: true,
+ scroll: true,
+ })[0].addEventListener("sortupdate", function(e) {
+ let order = $(".sidebar-menu > .treeview[data-id]").toArray().map(a => $(a).data("id"))
- stop: function (event, ui) {
- let order = $(this).sortable('toArray').toString();
-
- $.post(globals.rootdir + "/actions.php?id_module=" + globals.order_manager_id, {
- op: 'sort_modules',
- ids: order
+ $.post(globals.rootdir + "/actions.php", {
+ id_module: globals.order_manager_id,
+ op: "sort_modules",
+ order: order.join(","),
});
- }
- });
-
- if (globals.is_mobile) {
- $(".sidebar-menu").sortable("disable");
+ });
}
$(".sidebar-toggle").click(function () {
diff --git a/assets/src/js/base/supersearch.js b/assets/src/js/base/supersearch.js
index 37f153c09..23212355a 100644
--- a/assets/src/js/base/supersearch.js
+++ b/assets/src/js/base/supersearch.js
@@ -17,88 +17,75 @@
*/
$(document).ready(function () {
- $('#supersearch').keyup(function () {
- $(document).ajaxStop();
+ const searchInput = $('#supersearch');
+ const searchButton = searchInput.parent().find('i');
+ const searches = [];
- if ($(this).val() == '') {
- $(this).removeClass('wait');
- } else {
- $(this).addClass('wait');
- }
- });
+ autocomplete({
+ minLength: 1,
+ input: searchInput[0],
+ emptyMsg: globals.translations.noResults,
+ debounceWaitMs: 500,
+ fetch: function(text, update) {
+ text = text.toLowerCase();
- $.widget("custom.supersearch", $.ui.autocomplete, {
- _create: function () {
- this._super();
- this.widget().menu("option", "items", "> :not(.ui-autocomplete-category)");
- },
- _renderMenu: function (ul, items) {
- if (items[0].value == undefined) {
- $('#supersearch').removeClass('wait');
- ul.html('');
- } else {
- var that = this,
- currentCategory = "";
+ // Registrazione ricerca
+ searches.push(text);
+ searchButton
+ .removeClass('fa-search')
+ .addClass('fa-spinner fa-spin');
- ul.addClass('ui-autocomplete-scrollable');
- ul.css('z-index', '999');
-
- $.each(items, function (index, item) {
-
- if (item.category != currentCategory) {
- ul.append("
" + item.category + "");
- currentCategory = item.category;
- }
-
- that._renderItemData(ul, item);
- });
- }
- },
- _renderItem: function (ul, item) {
- return $("")
- .append("" + item.value + "
" + item.label + "")
- .appendTo(ul);
- }
- });
-
- // Configurazione supersearch
- var $super = $('#supersearch').supersearch({
- minLength: 3,
- select: function (event, ui) {
- location.href = ui.item.link;
- },
- source: function (request, response) {
$.ajax({
url: globals.rootdir + '/ajax_search.php',
- dataType: "json",
+ dataType: "JSON",
data: {
- term: request.term
+ term: text,
},
-
- complete: function (jqXHR) {
- $('#supersearch').removeClass('wait');
- },
-
success: function (data) {
- if (data == null) {
- response($.map(['a'], function (item) {
- return false;
- }));
- } else {
- response($.map(data, function (item) {
- labels = (item.labels).toString();
- labels = labels.replace('
,', '
');
+ // Fix per gestione risultati null
+ data = data ? data : [];
- return {
- label: labels,
- category: item.category,
- link: item.link,
- value: item.title
- }
- }));
+ // Trasformazione risultati in formato leggibile
+ const results = data.map(function (result) {
+ return {
+ label: result.label ? result.label : '' + result.title + '
' + result.labels
+ .join('').split('
,').join('
'),
+ group: result.category,
+ link: result.link,
+ value: result.title
+ }
+ });
+
+ // Rimozione ricerca in corso
+ searches.pop();
+ if (searches.length === 0) {
+ searchButton
+ .removeClass('fa-spinner fa-spin')
+ .addClass('fa-search');
}
+
+ update(results);
+ },
+ error: function (){
+ searchButton
+ .removeClass('fa-spinner fa-spin')
+ .addClass('fa-exclamation-triangle');
}
});
+ },
+ preventSubmit: true,
+ disableAutoSelect: true,
+ onSelect: function(item) {
+ window.location.href = item.link;
+ },
+ customize: function(input, inputRect, container, maxHeight) {
+ container.style.width = '600px';
+ },
+ render: function(item, currentValue){
+ const itemElement = document.createElement("div");
+ itemElement.innerHTML = item.label;
+ // " + item.value + "
" + item.label + "
+ return itemElement;
}
});
});
diff --git a/assets/src/js/base/widgets.js b/assets/src/js/base/widgets.js
index 4736df14a..3aae07b43 100644
--- a/assets/src/js/base/widgets.js
+++ b/assets/src/js/base/widgets.js
@@ -17,35 +17,36 @@
*/
$(document).ready(function () {
- $("#widget-top, #widget-right").sortable({
+ const widgets = sortable("#widget-top, #widget-right", {
+ forcePlaceholderSize: true,
items: 'li',
cursor: 'move',
dropOnEmpty: true,
- connectWith: '.widget',
+ acceptFrom: '.widget',
scroll: true,
- helper: 'clone',
- start: function (event, ui) {
- // Salvo la lista da cui proviene il drag
- src_list = ($(this).attr('id')).replace('widget-', '');
+ });
- // Evidenzio le aree dei widget
- $('.widget').addClass('bordered').sortable('refreshPositions');
- },
- stop: function (event, ui) {
+ for (const sorting of widgets) {
+ sorting.addEventListener("sortupdate", function (e) {
// Rimuovo l'evidenziazione dell'area widget
$('.widget').removeClass('bordered');
// Salvo la lista su cui ho eseguito il drop
- dst_list = (ui.item.parent().attr('id')).replace('widget-', '');
+ const location = $(e.detail.destination.container).attr('id').replace('widget-', '');
- var order = $(this).sortable('toArray').toString();
- $.post(globals.rootdir + "/actions.php?id_module=" + globals.order_manager_id, {
- op: 'sort_widgets',
- location: dst_list,
- ids: order,
+ let order = $(".widget li[data-id]").toArray().map(a => $(a).data("id"))
+ $.post(globals.rootdir + "/actions.php", {
+ id_module: globals.order_manager_id,
id_module_widget: globals.id_module,
- id_record: globals.id_record,
+ op: 'sort_widgets',
+ location: location,
+ order: order.join(','),
});
- }
- });
+ });
+
+ sorting.addEventListener("sortstart", function (e) {
+ // Evidenzio le aree dei widget
+ $('.widget').addClass('bordered');
+ });
+ }
});
diff --git a/assets/src/js/functions/allegati.js b/assets/src/js/functions/allegati.js
new file mode 100644
index 000000000..f15708843
--- /dev/null
+++ b/assets/src/js/functions/allegati.js
@@ -0,0 +1,308 @@
+/*
+ * OpenSTAManager: il software gestionale open source per l'assistenza tecnica e la fatturazione
+ * Copyright (C) DevCode s.r.l.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+// Disabling autoDiscover, otherwise Dropzone will try to attach twice.
+Dropzone.autoDiscover = false;
+
+/**
+ * Restituisce filename ed estensione di un file indicato.
+ * @param path
+ * @returns [string, string]
+ */
+function getFilenameAndExtension(path) {
+ let filename_extension = path.replace(/^.*[\\\/]/, '');
+ let filename = filename_extension.substring(0, filename_extension.lastIndexOf('.'));
+ let ext = filename_extension.split('.').pop();
+
+ return [filename, ext];
+}
+
+/**
+ * Inizializza la gestione degli allegati.
+ * @param gestione
+ */
+function initGestioneAllegati(gestione) {
+ const dropzone_id = '#' + gestione.attr('id') + ' .dropzone';
+ const maxFilesize = gestione.data('max_filesize');
+ if ($(dropzone_id).length === 0) {
+ return;
+ }
+
+ let params = new URLSearchParams({
+ op: "aggiungi-allegato",
+ id_module: gestione.data('id_module'),
+ id_plugin: gestione.data('id_plugin'),
+ id_record: gestione.data('id_record'),
+ }).toString();
+
+ let dragdrop = new Dropzone(dropzone_id, {
+ dictDefaultMessage: globals.translations.allegati.messaggio + ".
(" + globals.translations.allegati.maxFilesize.replace('_SIZE_', maxFilesize) + ")",
+ paramName: "file",
+ maxFilesize: maxFilesize, // MB
+ uploadMultiple: false,
+ parallelUploads: 2,
+ addRemoveLinks: false,
+ autoProcessQueue: true,
+ autoQueue: true,
+ url: globals.rootdir + "/actions.php?" + params,
+ init: function (file, xhr, formData) {
+ this.on("success", function (file) {
+ dragdrop.removeFile(file);
+ });
+
+ this.on("complete", function (file) {
+ // Ricarico solo quando ho finito
+ if (this.getUploadingFiles().length === 0 && this.getQueuedFiles().length === 0) {
+ ricaricaAllegati(gestione);
+ }
+ });
+ }
+ });
+}
+
+/**
+ * Funzione per l'apertura della schermata di modifica per una categoria di allegati.
+ * @param gestione
+ * @param pulsanteModifica
+ */
+function modificaCategoriaAllegati(gestione, pulsanteModifica) {
+ const categoria = $(pulsanteModifica).parent().parent();
+ console.log(categoria)
+
+ const nome = categoria.find(".box-title");
+ nome.addClass('hidden');
+ $(pulsanteModifica).addClass('hidden');
+
+ const pulsanteSalva = categoria.find(".category-save");
+ const pulsanteAnnulla = categoria.find(".category-cancel");
+ const inputNome = categoria.find(".category-name");
+ pulsanteSalva.removeClass("hidden");
+ pulsanteAnnulla.removeClass("hidden");
+ inputNome.removeClass("hidden");
+}
+
+/**
+ * Funzione per salvare le modifiche effettuate su una categoria di allegati.
+ * @param gestione
+ * @param pulsanteSalva
+ */
+function salvaCategoriaAllegati(gestione, pulsanteSalva) {
+ const categoria = $(pulsanteSalva).parent().parent();
+
+ const nome = categoria.find(".box-title");
+ const inputNome = categoria.find(".category-name");
+
+ mostraCaricamentoAllegati(gestione);
+
+ $.ajax({
+ url: globals.rootdir + "/actions.php",
+ cache: false,
+ type: "POST",
+ data: {
+ op: "modifica-categoria-allegato",
+ id_module: gestione.data('id_module'),
+ id_plugin: gestione.data('id_plugin'),
+ id_record: gestione.data('id_record'),
+ category: nome.text(),
+ name: inputNome.val(),
+ },
+ success: function (data) {
+ ricaricaAllegati(gestione);
+ },
+ error: function (gestione) {
+ ricaricaAllegati(gestione);
+ }
+ });
+}
+
+/**
+ * Funzione per caricare un nuovo allegato.
+ * @param gestione
+ */
+function aggiungiAllegato(gestione) {
+ const id = "#" + gestione.attr('id');
+ const form = $(id + " #upload-form");
+
+ form.ajaxSubmit({
+ url: globals.rootdir + "/actions.php",
+ data: data,
+ type: "post",
+ uploadProgress: function (event, position, total, percentComplete) {
+ $(id + " #upload").prop("disabled", true).html(percentComplete + "%").removeClass("btn-success").addClass("btn-info");
+ },
+ success: function (data) {
+ ricaricaAllegati(gestione);
+ },
+ error: function (data) {
+ alert(globals.translations.allegati.errore + ": " + data);
+ }
+ });
+}
+
+/**
+ * Funzione per mostrare il loader di caricamento per gli allegati.
+ * @param gestione
+ */
+function mostraCaricamentoAllegati(gestione) {
+ const id = "#" + gestione.attr('id');
+
+ localLoading($(id + " .panel-body"), true);
+}
+
+/**
+ * Funzione dedicata al caricamento dinamico degli allegati.
+ * @param gestione
+ */
+function ricaricaAllegati(gestione) {
+ const id = "#" + gestione.attr('id');
+
+ let params = new URLSearchParams({
+ op: "list_attachments",
+ id_module: gestione.data('id_module'),
+ id_plugin: gestione.data('id_plugin'),
+ id_record: gestione.data('id_record'),
+ }).toString();
+
+ $(id).load(globals.rootdir + "/ajax.php?" + params, function () {
+ localLoading($(id + " .panel-body"), false);
+
+ const nuovoAllegato = $(id + " table tr").eq(-1).attr("id");
+ if (nuovoAllegato !== undefined) {
+ $("#" + nuovoAllegato).effect("highlight", {}, 1500);
+ }
+ });
+}
+
+/**
+ * Funzione per l'apertura della pagina di gestione dei dati dell'allegato.
+ * @param button
+ */
+function modificaAllegato(button) {
+ const gestione = $(button).closest(".gestione-allegati");
+ const allegato = $(button).closest("tr").data();
+
+ let params = new URLSearchParams({
+ op: "visualizza-modifica-allegato",
+ id_module: gestione.data('id_module'),
+ id_plugin: gestione.data('id_plugin'),
+ id_record: gestione.data('id_record'),
+ id_allegato: allegato.id,
+ }).toString();
+
+ openModal(globals.translations.allegati.modifica, globals.rootdir + "/actions.php?" + params);
+}
+
+/**
+ * Funzione per gestire il download di un allegato.
+ * @param button
+ */
+function saggiungiAllegato(button) {
+ const gestione = $(button).closest(".gestione-allegati");
+ const allegato = $(button).closest("tr").data();
+
+ let params = new URLSearchParams({
+ op: "download-allegato",
+ id_module: gestione.data('id_module'),
+ id_plugin: gestione.data('id_plugin'),
+ id_record: gestione.data('id_record'),
+ id: allegato.id,
+ filename: allegato.filename,
+ }).toString();
+
+ window.open(globals.rootdir + "/actions.php?" + params, "_blank")
+}
+
+/**
+ * Funzione per l'apertura dell'anteprima di visualizzazione allegato.
+ * @param button
+ */
+function visualizzaAllegato(button) {
+ const allegato = $(button).closest("tr").data();
+
+ let params = new URLSearchParams({
+ file_id: allegato.id,
+ }).toString();
+
+ openModal(allegato.nome + ' (' + allegato.filename + ')', globals.rootdir + "/view.php?" + params);
+}
+
+/**
+ * Funzione per la gestione della rimozione di un allegato specifico.
+ *
+ * @param button
+ */
+function rimuoviAllegato(button) {
+ const gestione = $(button).closest(".gestione-allegati");
+ const allegato = $(button).closest("tr").data();
+
+ swal({
+ title: globals.translations.allegati.elimina,
+ type: "warning",
+ showCancelButton: true,
+ confirmButtonText: globals.translations.allegati.procedi,
+ }).then(function () {
+ mostraCaricamentoAllegati(gestione);
+
+ // Parametri della richiesta AJAX
+ let params = new URLSearchParams({
+ op: "rimuovi-allegato",
+ id_module: gestione.data('id_module'),
+ id_plugin: gestione.data('id_plugin'),
+ id_record: gestione.data('id_record'),
+ id_allegato: allegato.id,
+ filename: allegato.filename,
+ }).toString();
+
+ // Richiesta AJAX
+ $.ajax(globals.rootdir + "/actions.php?" + params)
+ .then(function () {
+ ricaricaAllegati(gestione);
+ });
+ }).catch(swal.noop);
+}
+
+function impostaCategorieAllegatiDisponibili(gestione, categorie) {
+ // Disabilitazione per rimozione input in aggiunta
+ return;
+
+ const id = "#" + gestione.attr('id');
+ const input = $("#modifica-allegato #categoria_allegato")[0];
+
+ autocomplete({
+ minLength: 0,
+ input: input,
+ emptyMsg: globals.translations.noResults,
+ fetch: function (text, update) {
+ text = text.toLowerCase();
+ const suggestions = categorie.filter(n => n.toLowerCase().startsWith(text));
+
+ // Trasformazione risultati in formato leggibile
+ const results = suggestions.map(function (result) {
+ return {
+ label: result,
+ value: result
+ }
+ });
+
+ update(results);
+ },
+ onSelect: function (item) {
+ input.value = item.label;
+ },
+ });
+}
diff --git a/assets/src/js/functions/form.js b/assets/src/js/functions/form.js
index fc249190c..a415454f2 100644
--- a/assets/src/js/functions/form.js
+++ b/assets/src/js/functions/form.js
@@ -158,6 +158,7 @@ function salvaForm(form, data = {}, button = null) {
buttonRestore(button, restore);
reject();
+ return;
}
// Gestione grafica di salvataggio
diff --git a/assets/src/js/functions/functions.js b/assets/src/js/functions/functions.js
index b0fff95b5..e77147816 100755
--- a/assets/src/js/functions/functions.js
+++ b/assets/src/js/functions/functions.js
@@ -52,7 +52,11 @@ function openModal(title, href) {
}
});
- var content = '\
+ // Promise per la gestione degli eventi
+ const d = $.Deferred();
+ $(id).one('shown.bs.modal', d.resolve);
+
+ const content = '