From 2964ba6975b493cb2d3ce01306d6a345c7400f7f Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Wed, 23 Jul 2014 19:43:43 -0400 Subject: [PATCH 001/208] #22 Now new tickets can be created, even with multiple pages --- inc/ticket_list.inc.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/inc/ticket_list.inc.php b/inc/ticket_list.inc.php index e89e578a..8d631833 100644 --- a/inc/ticket_list.inc.php +++ b/inc/ticket_list.inc.php @@ -174,6 +174,13 @@ if ($total > 0) } echo '

'; + echo ' +
+
+
+ '.$hesklang['nti'].' +
+
'; } // end PAGES > 1 else From ed940971617e3b8d77a94c9e71f8d517b448c2bc Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Wed, 23 Jul 2014 20:13:43 -0400 Subject: [PATCH 002/208] Updated version # and GA tracking --- README.md | 4 ++-- nuMods_settings.inc.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 23121fcf..9357fa19 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -[![Analytics](https://ga-beacon.appspot.com/UA-49251479-1/hesk/README)](https://github.com/mkoch227/Hesk) +[![Analytics](https://ga-beacon.appspot.com/UA-49251479-1/NuMods/README)](https://github.com/mkoch227/NuMods) -

NuMods v1.2.1

+

NuMods v1.2.3

This branch contains all files modified from the base version of HESK to become NuMods, a set of modifications for HESK v2.x diff --git a/nuMods_settings.inc.php b/nuMods_settings.inc.php index 0daf7510..515b16d6 100644 --- a/nuMods_settings.inc.php +++ b/nuMods_settings.inc.php @@ -14,4 +14,4 @@ $nuMods_settings['dropdownItemTextHoverBackgroundColor'] = '#f5f5f5'; $nuMods_settings['questionMarkColor'] = '#000000'; /* DO NOT EDIT ANYTHING BELOW THIS LINE */ -$nuMods_settings['version']='1.2.2'; +$nuMods_settings['version']='1.2.3'; From a4e1623b0aad3aeae5a6197156f1c94b45c6b54d Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 27 Jul 2014 20:14:15 -0400 Subject: [PATCH 003/208] Update README.md --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 9357fa19..5f6f4320 100644 --- a/README.md +++ b/README.md @@ -65,4 +65,3 @@ You can download this tweak via two ways:

Credits

Mike Koch - Creator of NuMods

Klemen Stirn - Creator of HESK

-

lupolo from PHPJunkyard Scripts - diligent bug reporting on the PHPJunkyard Scripts Forum

From 407e93fe2894f2011b40edcec6757aff2c9779d7 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Tue, 5 Aug 2014 20:26:33 -0400 Subject: [PATCH 004/208] Updated version numbers on license header --- admin/admin_main.php | 2 +- admin/admin_settings.php | 2 +- admin/admin_settings_save.php | 2 +- admin/admin_submit_ticket.php | 2 +- admin/change_status.php | 2 +- admin/edit_post.php | 2 +- admin/find_tickets.php | 2 +- admin/index.php | 2 +- admin/lock.php | 2 +- admin/manage_canned.php | 2 +- admin/manage_categories.php | 2 +- admin/manage_knowledgebase.php | 2 +- admin/manage_users.php | 2 +- admin/new_ticket.php | 2 +- admin/reports.php | 2 +- admin/show_tickets.php | 2 +- change_status.php | 2 +- inc/header.inc.php | 2 +- inc/print_tickets.inc.php | 2 +- inc/show_admin_nav.inc.php | 2 +- inc/show_search_form.inc.php | 2 +- inc/ticket_list.inc.php | 2 +- index.php | 2 +- install/index.php | 2 +- install/install.php | 2 +- install/install_functions.inc.php | 2 +- language/en/text.php | 2 +- submit_ticket.php | 2 +- suggest_articles.php | 2 +- suggest_email.php | 2 +- 30 files changed, 30 insertions(+), 30 deletions(-) diff --git a/admin/admin_main.php b/admin/admin_main.php index 052a0f57..f2cae84a 100644 --- a/admin/admin_main.php +++ b/admin/admin_main.php @@ -1,7 +1,7 @@ Date: Tue, 5 Aug 2014 20:26:47 -0400 Subject: [PATCH 005/208] Updated HESK to 2.5.5 (which is also NuMods 1.2.4) --- admin/admin_reply_ticket.php | 6 +++--- admin/admin_ticket.php | 14 +++++++------- admin/export.php | 14 +++++++++----- admin/knowledgebase_private.php | 4 ++-- admin/mail.php | 9 ++++++--- admin/profile.php | 4 ++-- inc/common.inc.php | 24 +++++++++++++++++++++--- inc/headerAdmin.inc.php | 4 ++-- inc/knowledgebase_functions.inc.php | 4 ++-- install/updateNuMods.php | 4 ++-- knowledgebase.php | 4 ++-- nuMods_settings.inc.php | 2 +- print.php | 8 ++++---- reply_ticket.php | 6 +++--- ticket.php | 8 ++++---- 15 files changed, 70 insertions(+), 45 deletions(-) diff --git a/admin/admin_reply_ticket.php b/admin/admin_reply_ticket.php index b8e0f8eb..c4b11321 100644 --- a/admin/admin_reply_ticket.php +++ b/admin/admin_reply_ticket.php @@ -1,7 +1,7 @@ $ticket['subject'], 'message' => stripslashes($message), 'attachments' => $myattachments, -'dt' => hesk_date($ticket['dt']), -'lastchange' => hesk_date($ticket['lastchange']), +'dt' => hesk_date($ticket['dt'], true), +'lastchange' => hesk_date($ticket['lastchange'], true), ); // 2. Add custom fields to the array diff --git a/admin/admin_ticket.php b/admin/admin_ticket.php index 8543c9cc..1bf456ff 100644 --- a/admin/admin_ticket.php +++ b/admin/admin_ticket.php @@ -1,7 +1,7 @@ $ticket['lastreplier'], 'subject' => $ticket['subject'], 'message' => stripslashes($msg), - 'dt' => hesk_date($ticket['dt']), - 'lastchange' => hesk_date($ticket['lastchange']), + 'dt' => hesk_date($ticket['dt'], true), + 'lastchange' => hesk_date($ticket['lastchange'], true), ); // 2. Add custom fields to the array @@ -443,11 +443,11 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');

  • - +

  • - +

  • @@ -773,7 +773,7 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php'); -


    : +


    :

    diff --git a/admin/export.php b/admin/export.php index 3644aac6..f497428a 100644 --- a/admin/export.php +++ b/admin/export.php @@ -1,7 +1,7 @@ '.$ticket['id'].' -'.$ticket['dt'].' -'.$ticket['lastchange'].' +'.hesk_date($ticket['dt'], true).' +'.hesk_date($ticket['lastchange'], true).' @@ -567,6 +568,9 @@ if (isset($_GET['w'])) $tickets_exported++; $this_round++; } // End of while loop + + // Go back to the HH:MM:SS format for hesk_date() + $hesk_settings['timeformat'] = 'H:i:s'; // Append any remaining rows into the file if ($this_round > 0) diff --git a/admin/knowledgebase_private.php b/admin/knowledgebase_private.php index 897c729e..24d23267 100644 --- a/admin/knowledgebase_private.php +++ b/admin/knowledgebase_private.php @@ -1,7 +1,7 @@ : - + : diff --git a/admin/mail.php b/admin/mail.php index 123a8b7f..1630580f 100644 --- a/admin/mail.php +++ b/admin/mail.php @@ -1,7 +1,7 @@ '.$admins[$pm[$hesk_settings['mailtmp']['other']]].'' : (($pm['from'] == 9999) ? 'HESK.com' : $hesklang['e_udel']); - $pm['dt'] = hesk_dateToString($pm['dt'],0,1); + + echo $pm['dt']; + + $pm['dt'] = hesk_dateToString($pm['dt'],0,1,0,true); ?> @@ -597,7 +600,7 @@ function mail_list_messages() $pm['subject'] = ''.$pm['subject'].''; } $pm['name'] = isset($admins[$pm[$hesk_settings['mailtmp']['other']]]) ? ''.$admins[$pm[$hesk_settings['mailtmp']['other']]].'' : (($pm['from'] == 9999) ? 'HESK.com' : $hesklang['e_udel']); - $pm['dt'] = hesk_dateToString($pm['dt'],0); + $pm['dt'] = hesk_dateToString($pm['dt'],0,0,0,true); echo << diff --git a/admin/profile.php b/admin/profile.php index c7fe5391..1971b542 100644 --- a/admin/profile.php +++ b/admin/profile.php @@ -1,7 +1,7 @@ '; } echo ' diff --git a/install/updateNuMods.php b/install/updateNuMods.php index b8251cd1..5163e852 100644 --- a/install/updateNuMods.php +++ b/install/updateNuMods.php @@ -61,11 +61,11 @@ if ($_GET['update'] == 1) ?> - NuMods 1.2.0 Install / Upgrade + NuMods 1.2.4 Install / Upgrade
    -

    Install / Upgrade NuMods to 1.2.0

    +

    Install / Upgrade NuMods to 1.2.4

    If you have not yet installed/updated HESK, please do so first before continuing; otherwise installation will fail!


    Please verify the database information below. Addtionally, ensure that the database user has CREATE permissions.

    diff --git a/knowledgebase.php b/knowledgebase.php index 70aa932d..8ab5292f 100644 --- a/knowledgebase.php +++ b/knowledgebase.php @@ -1,7 +1,7 @@ -

    :

    +

    :

    ' . hesk_unhortenUrl($ticket['message']) . '

    '; // Print replies while ($reply = hesk_dbFetchAssoc($res)) { - $reply['dt'] = hesk_date($reply['dt']); + $reply['dt'] = hesk_date($reply['dt'], true); echo '
    diff --git a/reply_ticket.php b/reply_ticket.php index be9a2bc1..7c09275c 100644 --- a/reply_ticket.php +++ b/reply_ticket.php @@ -1,7 +1,7 @@ $ticket['subject'], 'message' => stripslashes($message), 'attachments' => $myattachments, -'dt' => hesk_date($ticket['dt']), -'lastchange' => hesk_date($ticket['lastchange']), +'dt' => hesk_date($ticket['dt'], true), +'lastchange' => hesk_date($ticket['lastchange'], true), ); // 2. Add custom fields to the array diff --git a/ticket.php b/ticket.php index 12effbfc..671b4774 100644 --- a/ticket.php +++ b/ticket.php @@ -1,7 +1,7 @@
    ' . hesk_date($article['dt'], true) . '
    -

    :     :

    +

    :     :

    -

    :

    +

    :

    $v) @@ -598,7 +598,7 @@ function hesk_printCustomerTicketReplies() $unread_replies[] = $reply['id']; } - $reply['dt'] = hesk_date($reply['dt']); + $reply['dt'] = hesk_date($reply['dt'], true); ?>
    From 3883c93229a0e78fb2f231daa9fbf23adf441d33 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Tue, 5 Aug 2014 20:27:34 -0400 Subject: [PATCH 006/208] Updated README --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index 5f6f4320..8c06c1f4 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,4 @@ -[![Analytics](https://ga-beacon.appspot.com/UA-49251479-1/NuMods/README)](https://github.com/mkoch227/NuMods) - -

    NuMods v1.2.3

    +

    NuMods v1.2.4

    This branch contains all files modified from the base version of HESK to become NuMods, a set of modifications for HESK v2.x From 06adabf887623480215d201d2a926408585e7377 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Tue, 5 Aug 2014 20:37:36 -0400 Subject: [PATCH 007/208] Updated .gitignore --- .gitignore | 92 +++++++++++++++++++++++++++--------------------------- 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/.gitignore b/.gitignore index 05965a6e..cb56f7f4 100644 --- a/.gitignore +++ b/.gitignore @@ -199,52 +199,52 @@ inc/tabs/tabber-minimized.js inc/tabs/tabber.css inc/timer/hesk_timer.js inc/timer/index.htm -inc/tiny_mce/3.5.10/langs/en.js -inc/tiny_mce/3.5.10/license.txt -inc/tiny_mce/3.5.10/themes/advanced/about.htm -inc/tiny_mce/3.5.10/themes/advanced/anchor.htm -inc/tiny_mce/3.5.10/themes/advanced/charmap.htm -inc/tiny_mce/3.5.10/themes/advanced/color_picker.htm -inc/tiny_mce/3.5.10/themes/advanced/editor_template.js -inc/tiny_mce/3.5.10/themes/advanced/image.htm -inc/tiny_mce/3.5.10/themes/advanced/img/colorpicker.jpg -inc/tiny_mce/3.5.10/themes/advanced/img/flash.gif -inc/tiny_mce/3.5.10/themes/advanced/img/icons.gif -inc/tiny_mce/3.5.10/themes/advanced/img/iframe.gif -inc/tiny_mce/3.5.10/themes/advanced/img/pagebreak.gif -inc/tiny_mce/3.5.10/themes/advanced/img/quicktime.gif -inc/tiny_mce/3.5.10/themes/advanced/img/realmedia.gif -inc/tiny_mce/3.5.10/themes/advanced/img/shockwave.gif -inc/tiny_mce/3.5.10/themes/advanced/img/trans.gif -inc/tiny_mce/3.5.10/themes/advanced/img/video.gif -inc/tiny_mce/3.5.10/themes/advanced/img/windowsmedia.gif -inc/tiny_mce/3.5.10/themes/advanced/js/about.js -inc/tiny_mce/3.5.10/themes/advanced/js/anchor.js -inc/tiny_mce/3.5.10/themes/advanced/js/charmap.js -inc/tiny_mce/3.5.10/themes/advanced/js/color_picker.js -inc/tiny_mce/3.5.10/themes/advanced/js/image.js -inc/tiny_mce/3.5.10/themes/advanced/js/link.js -inc/tiny_mce/3.5.10/themes/advanced/js/source_editor.js -inc/tiny_mce/3.5.10/themes/advanced/langs/en.js -inc/tiny_mce/3.5.10/themes/advanced/langs/en_dlg.js -inc/tiny_mce/3.5.10/themes/advanced/link.htm -inc/tiny_mce/3.5.10/themes/advanced/shortcuts.htm -inc/tiny_mce/3.5.10/themes/advanced/skins/default/content.css -inc/tiny_mce/3.5.10/themes/advanced/skins/default/dialog.css -inc/tiny_mce/3.5.10/themes/advanced/skins/default/img/buttons.png -inc/tiny_mce/3.5.10/themes/advanced/skins/default/img/items.gif -inc/tiny_mce/3.5.10/themes/advanced/skins/default/img/menu_arrow.gif -inc/tiny_mce/3.5.10/themes/advanced/skins/default/img/menu_check.gif -inc/tiny_mce/3.5.10/themes/advanced/skins/default/img/progress.gif -inc/tiny_mce/3.5.10/themes/advanced/skins/default/img/tabs.gif -inc/tiny_mce/3.5.10/themes/advanced/skins/default/ui.css -inc/tiny_mce/3.5.10/themes/advanced/source_editor.htm -inc/tiny_mce/3.5.10/tiny_mce.js -inc/tiny_mce/3.5.10/tiny_mce_popup.js -inc/tiny_mce/3.5.10/utils/editable_selects.js -inc/tiny_mce/3.5.10/utils/form_utils.js -inc/tiny_mce/3.5.10/utils/mctabs.js -inc/tiny_mce/3.5.10/utils/validate.js +inc/tiny_mce/3.5.11/langs/en.js +inc/tiny_mce/3.5.11/license.txt +inc/tiny_mce/3.5.11/themes/advanced/about.htm +inc/tiny_mce/3.5.11/themes/advanced/anchor.htm +inc/tiny_mce/3.5.11/themes/advanced/charmap.htm +inc/tiny_mce/3.5.11/themes/advanced/color_picker.htm +inc/tiny_mce/3.5.11/themes/advanced/editor_template.js +inc/tiny_mce/3.5.11/themes/advanced/image.htm +inc/tiny_mce/3.5.11/themes/advanced/img/colorpicker.jpg +inc/tiny_mce/3.5.11/themes/advanced/img/flash.gif +inc/tiny_mce/3.5.11/themes/advanced/img/icons.gif +inc/tiny_mce/3.5.11/themes/advanced/img/iframe.gif +inc/tiny_mce/3.5.11/themes/advanced/img/pagebreak.gif +inc/tiny_mce/3.5.11/themes/advanced/img/quicktime.gif +inc/tiny_mce/3.5.11/themes/advanced/img/realmedia.gif +inc/tiny_mce/3.5.11/themes/advanced/img/shockwave.gif +inc/tiny_mce/3.5.11/themes/advanced/img/trans.gif +inc/tiny_mce/3.5.11/themes/advanced/img/video.gif +inc/tiny_mce/3.5.11/themes/advanced/img/windowsmedia.gif +inc/tiny_mce/3.5.11/themes/advanced/js/about.js +inc/tiny_mce/3.5.11/themes/advanced/js/anchor.js +inc/tiny_mce/3.5.11/themes/advanced/js/charmap.js +inc/tiny_mce/3.5.11/themes/advanced/js/color_picker.js +inc/tiny_mce/3.5.11/themes/advanced/js/image.js +inc/tiny_mce/3.5.11/themes/advanced/js/link.js +inc/tiny_mce/3.5.11/themes/advanced/js/source_editor.js +inc/tiny_mce/3.5.11/themes/advanced/langs/en.js +inc/tiny_mce/3.5.11/themes/advanced/langs/en_dlg.js +inc/tiny_mce/3.5.11/themes/advanced/link.htm +inc/tiny_mce/3.5.11/themes/advanced/shortcuts.htm +inc/tiny_mce/3.5.11/themes/advanced/skins/default/content.css +inc/tiny_mce/3.5.11/themes/advanced/skins/default/dialog.css +inc/tiny_mce/3.5.11/themes/advanced/skins/default/img/buttons.png +inc/tiny_mce/3.5.11/themes/advanced/skins/default/img/items.gif +inc/tiny_mce/3.5.11/themes/advanced/skins/default/img/menu_arrow.gif +inc/tiny_mce/3.5.11/themes/advanced/skins/default/img/menu_check.gif +inc/tiny_mce/3.5.11/themes/advanced/skins/default/img/progress.gif +inc/tiny_mce/3.5.11/themes/advanced/skins/default/img/tabs.gif +inc/tiny_mce/3.5.11/themes/advanced/skins/default/ui.css +inc/tiny_mce/3.5.11/themes/advanced/source_editor.htm +inc/tiny_mce/3.5.11/tiny_mce.js +inc/tiny_mce/3.5.11/tiny_mce_popup.js +inc/tiny_mce/3.5.11/utils/editable_selects.js +inc/tiny_mce/3.5.11/utils/form_utils.js +inc/tiny_mce/3.5.11/utils/mctabs.js +inc/tiny_mce/3.5.11/utils/validate.js inc/treemenu/TreeMenu.php inc/treemenu/index.htm inc/users_online.inc.php From 680a2a16b1f04487c6247b1052c22995e1ff4a1d Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Tue, 5 Aug 2014 20:48:20 -0400 Subject: [PATCH 008/208] Added update for v1.2.4 --- install/install_functions.inc.php | 4 +- install/updateNuMods.php | 6 +- install/updateTo1-2-4.php | 223 ++++++++++++++++++++++++++++++ 3 files changed, 229 insertions(+), 4 deletions(-) create mode 100644 install/updateTo1-2-4.php diff --git a/install/install_functions.inc.php b/install/install_functions.inc.php index 12047b9c..e7bc6b92 100644 --- a/install/install_functions.inc.php +++ b/install/install_functions.inc.php @@ -36,8 +36,8 @@ if (!defined('IN_SCRIPT')) {die('Invalid attempt');} // We will be installing this HESK version: -define('HESK_NEW_VERSION','2.5.3'); -define('NUMODS_NEW_VERSION','1.2.0'); +define('HESK_NEW_VERSION','2.5.5'); +define('NUMODS_NEW_VERSION','1.2.4'); // Other required files and settings define('INSTALL',1); diff --git a/install/updateNuMods.php b/install/updateNuMods.php index 5163e852..4c435213 100644 --- a/install/updateNuMods.php +++ b/install/updateNuMods.php @@ -65,7 +65,9 @@ if ($_GET['update'] == 1)
    -

    Install / Upgrade NuMods to 1.2.4

    +

    Update NuMods from v1.2.0 - v1.2.3 to v1.2.4

    +

    If you have NuMods v1.2.0 - v1.2.3, click here to update to v1.2.4. Do not use the installation below!

    +

    Install NuMods v1.2.4 from a version before 1.2.0

    If you have not yet installed/updated HESK, please do so first before continuing; otherwise installation will fail!


    Please verify the database information below. Addtionally, ensure that the database user has CREATE permissions.

    @@ -81,4 +83,4 @@ if ($_GET['update'] == 1)

    The installation / upgrade of NuMods has finished. You can now delete the install directory and access the admin area

    - \ No newline at end of file + diff --git a/install/updateTo1-2-4.php b/install/updateTo1-2-4.php new file mode 100644 index 00000000..7be61d3a --- /dev/null +++ b/install/updateTo1-2-4.php @@ -0,0 +1,223 @@ + + +NOTICE: You already have version 1.2.3 (Hesk version ' . HESK_NEW_VERSION . ') installed. + +'); +} + +if ($hesk_settings['hesk_version'] != HESK_OLD_VERSION) +{ +die(' +
    +
    +ERROR: You do not have version 1.2.3 (Hesk version ' . HESK_OLD_VERSION . ')
    +
    +This patch may only be used with NuMods version 1.2.3 (Hesk version ' . HESK_OLD_VERSION . '), your HESK version is ' . $hesk_settings['hesk_version'] . '
    +
    +You should Download full version ' . HESK_NEW_VERSION .' instead, and NuMods from http://numods.mkochcs.com.
    +
    +
    '); +} + +define('HIDE_ONLINE',1); + +/* Debugging should be enabled in installation mode */ +$hesk_settings['debug_mode'] = 1; +error_reporting(E_ALL); +$__maindir = dirname(dirname(__FILE__)) . '/'; + +hesk_iHeader(); +?> +
    + +
    + + + + + + + + + + + + + + + + +
      + + +

    Verifying HESK installation

    + +

     

    + +

    Verifying your HESK installation...

    + + +

    OK: new files uploaded.

    + +

     

    + + +

    » Your HESK has been updated to version .

    +

    » To complete setup delete the /install folder from your server.

    + +

    Update failed: Cannot write to your hesk_settings.inc.php file.

    + +

    Please make sure the hesk_settings.inc.php file is writable by PHP then click the Try again button below.

    + +
    +

    +
    + +

    Missing files!

    + +

     

    + +

    Please upload all HESK patch files to your server.

    + +
    +

    +
    + + +

     

    +

     

    +

     

    + +
     
    +
    + + + + + + Install Hesk <?php echo HESK_NEW_VERSION; ?> + + + + + + + +
    + + + + + +
    + + + + + + +
    HESK installation script
    + +
    + + +

     
    Powered by Help Desk Software HESK - brought to you by Help Desk Software SysAid

    + + From e6d1d715da1caa1d580fd40f8a9cd1d0b65fc56c Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Wed, 6 Aug 2014 21:57:18 -0400 Subject: [PATCH 009/208] Now the index page uses a panel instead of a hacky tab bar. It is also more responsive. --- css/hesk_newStyle.php | 10 --- inc/knowledgebase_functions.inc.php | 1 - index.php | 99 +++++++++++++---------------- 3 files changed, 45 insertions(+), 65 deletions(-) diff --git a/css/hesk_newStyle.php b/css/hesk_newStyle.php index 79f154c4..e28935f7 100644 --- a/css/hesk_newStyle.php +++ b/css/hesk_newStyle.php @@ -212,16 +212,6 @@ div.rightSideDash { padding-left: 18px; padding-right: 18px; } -div.enclosingDashboard { - margin-left: 50px; - margin-right: 50px; -} -.moreToLeft { - margin-right: 25px; -} -.viewTicketSidebar { - padding: 25px; -} div.enclosing { background-color: #fff; color: #4a5571; diff --git a/inc/knowledgebase_functions.inc.php b/inc/knowledgebase_functions.inc.php index 81b8f051..52cd71ee 100644 --- a/inc/knowledgebase_functions.inc.php +++ b/inc/knowledgebase_functions.inc.php @@ -289,7 +289,6 @@ function hesk_kbSearchLarge($admin = '') $action = $admin ? 'knowledgebase_private.php' : 'knowledgebase.php'; ?> -
    diff --git a/index.php b/index.php index cd7b5d2a..31ae6143 100644 --- a/index.php +++ b/index.php @@ -101,29 +101,24 @@ function print_add_ticket() -
    -
    - -
    -
    -
    -
    - -
    -
    - -
    +
    +
    +
    +
    +
    +
    -

    -
    -
    -
    +
    + +
    +
    +

    +
    +
    -
    +
  • -
    -
    -
    - -
    - -
    -
    - - -
    - -
    - - -
    -
    - /> -
    - - - - -
    -
    +
    +
    +
    +
    +
    +
    +
    + + +
    + +
    + + +
    +
    + /> +
    + + +
    +
    +
    -
    +
    Date: Thu, 7 Aug 2014 22:06:27 -0400 Subject: [PATCH 010/208] Starting to work on some more responsive layout for ticket.php --- ticket.php | 351 ++++++++++++++++++++++++++--------------------------- 1 file changed, 175 insertions(+), 176 deletions(-) diff --git a/ticket.php b/ticket.php index 671b4774..10e0afdd 100644 --- a/ticket.php +++ b/ticket.php @@ -207,200 +207,199 @@ require_once(HESK_PATH . 'inc/header.inc.php');
  • -
    -
    -
    -
    - -
    -
    -
    -
    - -
    -
    - -
    -
    -

    -
    -
    -
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    + +
    +
    +

    +
    -
    -  

    '; - - unset($_SESSION['force_form_top']); - } - ?> -

    :

    -
    -
    - - - - - - - - - - - ';} - elseif ($ticket['priority'] == 1) {echo 'class="highPriority">';} - else {echo 'class="medLowPriority">';} - - echo '

    '.$hesklang['priority'].'

    '; - - if ($ticket['priority']==0) {echo '

    '.$hesklang['critical'].'

    ';} - elseif ($ticket['priority']==1) {echo '

    '.$hesklang['high'].'

    ';} - elseif ($ticket['priority']==2) {echo '

    '.$hesklang['medium'].'

    ';} - else {echo '

    '.$hesklang['low'].'

    ';} - echo ''; - } - else - { - $hesk_settings['ticketColumnWidth'] = 5; - } - echo ''; - echo ''; - echo ''; - echo ''; - ?> - -
    -

    -
    -

    :     :

    -
    -

    '.$hesklang['open_action'].'';} - else {echo ''.$hesklang['close_action'].'';} ?>

    -

    '.$hesklang['status'].'

    '; - $ticketStatusKey = $ticket['statusKey']; - echo '

    '.$hesklang[$ticketStatusKey].'

    '; - echo '

    '.$hesklang['last_replier'].'

    -

    '.$ticket['repliername'].'

    '.$hesklang['category'].'

    -

    '.$category['name'].'

    '.$hesklang['replies'].'

    -

    '.$replies.'

    - - - +
    +  

    '; + + unset($_SESSION['force_form_top']); } + ?> +

    :

    +
    +
    +
    +
    +
    +

    +
    +
    +
    +
    +

    :     :

    +
    +
    +

    '.$hesklang['open_action'].'';} + else {echo ''.$hesklang['close_action'].'';} ?>

    +
    +
    - /* Make sure original message is in correct color if newest are on top */ - $color = 'class="ticketMessageContainer"'; - ?> -
    -
    -
    -
    -
    -
    - -

    :

    - - $v) - { - if ($v['use'] && $v['place']==0) - { - echo ' -

    '.$v['name'].': '.$ticket[$k].'

    '; - } - } - ?> -
    -
    - -

    :

    -


     

    -
    -
    - - +
    + + + + ';} + elseif ($ticket['priority'] == 1) {echo 'class="highPriority">';} + else {echo 'class="medLowPriority">';} + + echo '

    '.$hesklang['priority'].'

    '; + + if ($ticket['priority']==0) {echo '

    '.$hesklang['critical'].'

    ';} + elseif ($ticket['priority']==1) {echo '

    '.$hesklang['high'].'

    ';} + elseif ($ticket['priority']==2) {echo '

    '.$hesklang['medium'].'

    ';} + else {echo '

    '.$hesklang['low'].'

    ';} + echo ''; + } + else + { + $hesk_settings['ticketColumnWidth'] = 5; + } + echo ''; + echo ''; + echo ''; + echo ''; + ?> + +

    '.$hesklang['status'].'

    '; + $ticketStatusKey = $ticket['statusKey']; + echo '

    '.$hesklang[$ticketStatusKey].'

    '; + echo '

    '.$hesklang['last_replier'].'

    +

    '.$ticket['repliername'].'

    '.$hesklang['category'].'

    +

    '.$category['name'].'

    '.$hesklang['replies'].'

    +

    '.$replies.'

    + + + +
    +
    +
    +
    +
    +
    +
    + +

    :

    + + $v) { - if ($v['use'] && $v['place']) + if ($v['use'] && $v['place']==0) { echo '

    '.$v['name'].': '.$ticket[$k].'

    '; } } - /* Attachments */ - hesk_listAttachments($ticket['attachments'], $i); ?> -
    +
    +
    + +

    :

    +


     

    +
    +
    + + $v) + { + if ($v['use'] && $v['place']) + { + echo ' +

    '.$v['name'].': '.$ticket[$k].'

    '; + } + } + /* Attachments */ + hesk_listAttachments($ticket['attachments'], $i); + ?>
    - + + + - - + ?> - -
    -
    -
    + +
    +
    From 80d68ae01d3ef428c7903b86e563c2c18eb29b12 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Fri, 8 Aug 2014 22:01:46 -0400 Subject: [PATCH 011/208] Got a bit further in the responsive green row. Still some work to do. --- ticket.php | 72 ++++++++++++++++++++++++------------------------------ 1 file changed, 32 insertions(+), 40 deletions(-) diff --git a/ticket.php b/ticket.php index 10e0afdd..131e1ed3 100644 --- a/ticket.php +++ b/ticket.php @@ -269,49 +269,41 @@ require_once(HESK_PATH . 'inc/header.inc.php'); if ($ticket['isClosed'] == true && $ticket['locked'] != 1 && $hesk_settings['custopen']) {echo ''.$hesklang['open_action'].'';} else {echo ''.$hesklang['close_action'].'';} ?>

    -
    - -
    -
    - - - +
    ';} - elseif ($ticket['priority'] == 1) {echo 'class="highPriority">';} - else {echo 'class="medLowPriority">';} - - echo '

    '.$hesklang['priority'].'

    '; - - if ($ticket['priority']==0) {echo '

    '.$hesklang['critical'].'

    ';} - elseif ($ticket['priority']==1) {echo '

    '.$hesklang['high'].'

    ';} - elseif ($ticket['priority']==2) {echo '

    '.$hesklang['medium'].'

    ';} - else {echo '

    '.$hesklang['low'].'

    ';} - echo ''; - } - else - { - $hesk_settings['ticketColumnWidth'] = 5; - } - echo '
    '; - echo ''; - echo ''; - echo ''; + if ($hesk_settings['cust_urgency']) + { + $repliesColumnWidth = 2; + echo '
    ';} + elseif ($ticket['priority'] == 1) {echo 'highPriority">';} + else {echo 'medLowPriority" style="border-right: solid 1px #ddd; margin-top: 1px;">';} + echo '

    '.$hesklang['priority'].'

    '; + + if ($ticket['priority']==0) {echo '

    '.$hesklang['critical'].'

    ';} + elseif ($ticket['priority']==1) {echo '

    '.$hesklang['high'].'

    ';} + elseif ($ticket['priority']==2) {echo '

    '.$hesklang['medium'].'

    ';} + else {echo '

    '.$hesklang['low'].'

    ';} + echo '
    '; + } + else + { + $hesk_settings['ticketColumnWidth'] = 3; + } + echo '

    '.$hesklang['status'].'

    '; + $ticketStatusKey = $ticket['statusKey']; + echo '

    '.$hesklang[$ticketStatusKey].'

    '; + echo '
    '; + echo '

    '.$hesklang['last_replier'].'

    +

    '.$ticket['repliername'].'

    '; + echo '

    '.$hesklang['category'].'

    +

    '.$category['name'].'

    '; + echo '

    '.$hesklang['replies'].'

    +

    '.$replies.'

    '; ?> - -

    '.$hesklang['status'].'

    '; - $ticketStatusKey = $ticket['statusKey']; - echo '

    '.$hesklang[$ticketStatusKey].'

    '; - echo '

    '.$hesklang['last_replier'].'

    -

    '.$ticket['repliername'].'

    '.$hesklang['category'].'

    -

    '.$category['name'].'

    '.$hesklang['replies'].'

    -

    '.$replies.'

    +
    +
    Date: Sat, 9 Aug 2014 00:09:35 -0400 Subject: [PATCH 012/208] The ticket page is now more responsive --- css/hesk_newStyle.php | 31 +++++++++++++++++++++++++++++++ ticket.php | 22 +++++++++++++--------- 2 files changed, 44 insertions(+), 9 deletions(-) diff --git a/css/hesk_newStyle.php b/css/hesk_newStyle.php index e28935f7..4cf8ca83 100644 --- a/css/hesk_newStyle.php +++ b/css/hesk_newStyle.php @@ -18,6 +18,37 @@ $questionMarkColor = $nuMods_settings['questionMarkColor']; ?> +@media (max-width:991px) { + .close-ticket { + text-align: left; + } +} + +@media (min-width:992px) { + .close-ticket { + text-align: right; + } +} + + +@media (max-width:991px) { + .ticket-cell { + border-bottom: solid 1px #ddd; + border-right: 0; + padding-top: 5px; + } +} + +@media (min-width:992px) { + .ticket-cell { + border-bottom: 0; + border-right: solid 1px #ddd; + margin-top: 1px; + height: 90px; + padding-top: 10px; + } +} + .row { margin-left: 0px; margin-right: 0px; diff --git a/ticket.php b/ticket.php index 131e1ed3..d2fea055 100644 --- a/ticket.php +++ b/ticket.php @@ -261,10 +261,13 @@ require_once(HESK_PATH . 'inc/header.inc.php');
    -
    -

    :     :

    +
    +

    :

    -
    +
    +

    :

    +
    +

    '.$hesklang['open_action'].'';} else {echo ''.$hesklang['close_action'].'';} ?>

    @@ -275,10 +278,10 @@ require_once(HESK_PATH . 'inc/header.inc.php'); if ($hesk_settings['cust_urgency']) { $repliesColumnWidth = 2; - echo '
    ';} elseif ($ticket['priority'] == 1) {echo 'highPriority">';} - else {echo 'medLowPriority" style="border-right: solid 1px #ddd; margin-top: 1px;">';} + else {echo 'medLowPriority">';} echo '

    '.$hesklang['priority'].'

    '; if ($ticket['priority']==0) {echo '

    '.$hesklang['critical'].'

    ';} @@ -291,19 +294,20 @@ require_once(HESK_PATH . 'inc/header.inc.php'); { $hesk_settings['ticketColumnWidth'] = 3; } - echo '

    '.$hesklang['status'].'

    '; + echo '

    '.$hesklang['status'].'

    '; $ticketStatusKey = $ticket['statusKey']; echo '

    '.$hesklang[$ticketStatusKey].'

    '; echo '
    '; - echo '

    '.$hesklang['last_replier'].'

    + echo '

    '.$hesklang['last_replier'].'

    '.$ticket['repliername'].'

    '; - echo '

    '.$hesklang['category'].'

    + echo '

    '.$hesklang['category'].'

    '.$category['name'].'

    '; - echo '

    '.$hesklang['replies'].'

    + echo '

    '.$hesklang['replies'].'

    '.$replies.'

    '; ?>
    +
    Date: Sat, 9 Aug 2014 00:12:38 -0400 Subject: [PATCH 013/208] Now the ticket input page uses a panel instead of a hacky tab --- ticket.php | 125 +++++++++++++++++++++++++---------------------------- 1 file changed, 60 insertions(+), 65 deletions(-) diff --git a/ticket.php b/ticket.php index d2fea055..314a10d1 100644 --- a/ticket.php +++ b/ticket.php @@ -423,87 +423,82 @@ function print_form()
  • -
    -
    -
    -
    - -
    -
    -

    -
    -
    -
    +
    +
    +
    +
    + +
    +
    +

    +
    -
    +
    +
    + +

    +
    +
    +
    +
    + +
    + +
    +
    -

    -
    +
    + +
    + +
    +
    +
    +
    +
    + +
    +
    +
    + +
    +
    + + +
    + +
    +
    +
    +
    +

    -
    +
    - +
    - +
    -
    - -
    - -
    -
    -
    -
    -
    - -
    -
    -
    - -
    - - -
    - +
    -
    -

    -
    -
    -
    - -
    - -
    -
    -
    -
    - -
    -
    -
    -
    -
    Date: Sat, 9 Aug 2014 00:14:54 -0400 Subject: [PATCH 014/208] Knowledgebase page now uses panel instead of tabs --- knowledgebase.php | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/knowledgebase.php b/knowledgebase.php index 8ab5292f..b627cfc0 100644 --- a/knowledgebase.php +++ b/knowledgebase.php @@ -150,27 +150,24 @@ function hesk_kb_header($kb_link) {
  • -
    -
    -
    -
    - -
    -
    -

    -
    -
    -
    -
    -
    - +
    +
    +
    + +
    +
    +

    +
    +
    +
    +
    + Date: Sat, 9 Aug 2014 00:23:16 -0400 Subject: [PATCH 015/208] Install pages updated to panels --- install/install.php | 18 +-- install/install_functions.inc.php | 196 +++++++++++++++--------------- 2 files changed, 107 insertions(+), 107 deletions(-) diff --git a/install/install.php b/install/install.php index 70c7f286..e204121d 100644 --- a/install/install.php +++ b/install/install.php @@ -156,15 +156,17 @@ function hesk_iFinish() ?>
    -
    - -
    -

    Congratulations, you have successfully completed HESK database setup!

    -
    +
    +
    +
    +

    Summary

    +
    +
    +

    Congratulations, you have successfully completed HESK database setup!

    +
    +
    -
    +
    Success! HESK Successfully installed
    Next Steps:

      diff --git a/install/install_functions.inc.php b/install/install_functions.inc.php index e7bc6b92..2f6682fb 100644 --- a/install/install_functions.inc.php +++ b/install/install_functions.inc.php @@ -342,96 +342,92 @@ function hesk_iDatabase($problem=0)
      - -
      - - -
      Double-check all the information below. Contact your hosting company for the correct information to use!

      MySQL said: '.$mysql_log.'

      ', 'Database connection failed'; - } - elseif ($problem == 2) - { - echo 'Database tables already exist!

      - HESK database tables with '.$hesk_settings['db_pfix'].' prefix already exist in this database!

      - To upgrade an existing HESK installation select Update existing install instead.

      - To install a new copy of HESK in use a unique table prefix.'; - } - elseif ($problem == 3) - { - echo 'Old database tables not found!

      - HESK database tables have not been found in this database!

      - To install HESK use the New install option instead.'; - } - elseif ($problem == 4) - { - echo 'Version '.HESK_NEW_VERSION.' tables already exist!

      - Your database seems to be compatible with HESK version '.HESK_NEW_VERSION.'

      - To install a new copy of HESK use the New install option instead.'; - } - else - { - echo '

      To complete setup HESK needs to connect to your database. You can get this information from your hosting control panel.

      '; - } - ?> - -
      +
      +
      +

      Summary

      +
      +
      +
      Double-check all the information below. Contact your hosting company for the correct information to use!

      MySQL said: '.$mysql_log.'

      ', 'Database connection failed'; + } + elseif ($problem == 2) + { + echo 'Database tables already exist!

      + HESK database tables with '.$hesk_settings['db_pfix'].' prefix already exist in this database!

      + To upgrade an existing HESK installation select Update existing install instead.

      + To install a new copy of HESK in use a unique table prefix.'; + } + elseif ($problem == 3) + { + echo 'Old database tables not found!

      + HESK database tables have not been found in this database!

      + To install HESK use the New install option instead.'; + } + elseif ($problem == 4) + { + echo 'Version '.HESK_NEW_VERSION.' tables already exist!

      + Your database seems to be compatible with HESK version '.HESK_NEW_VERSION.'

      + To install a new copy of HESK use the New install option instead.'; + } + else + { + echo '

      To complete setup HESK needs to connect to your database. You can get this information from your hosting control panel.

      '; + } + ?> +
      +
      - -
      - - -
      3. Database Settings
      -
      -
      Database Settings
      -
      - -
      - - -
      -
      - - -
      -
      - - -
      -
      - - -
      - -
      - - -
      -
      -
      HESK Login Details
      -
      Username and password you will use to login into HESK administration.
      -
      +
      +
      3. Database Settings
      + +
      Database Settings
      +
      -
      - - -
      -
      - - -
      +
      + + +
      +
      + + +
      +
      + + +
      +
      + + +
      + +
      + + +
      +
      +
      HESK Login Details
      +
      Username and password you will use to login into HESK administration.
      +
      + +
      + + +
      +
      + + +
      + } + ?> -

      - +

      +
      -
      - -
      -
        -
      • The script is provided "as is", without any warranty. Use at your own risk.
         
      • -
      • HESK is a registered trademark, using the term HESK requires permission.
         
      • -
      • Do not redistribute this script without express written permission
         
      • -
      • If you wish to remove the "Powered by" links a license is required.
      • -
      -
      +
      +
      +
      +

      Summary

      +
      +
      +
        +
      • The script is provided "as is", without any warranty. Use at your own risk.
         
      • +
      • HESK is a registered trademark, using the term HESK requires permission.
         
      • +
      • Do not redistribute this script without express written permission
         
      • +
      • If you wish to remove the "Powered by" links a license is required.
      • +
      +
      +
      -
      +
      1. License Agreement
      The entire agreement:
      From 4d5e7dcbe150a98bf684c89b3ad48500d3355bae Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sat, 9 Aug 2014 16:00:36 -0400 Subject: [PATCH 016/208] Now the manage users page utilizes a panel instead of a tabbed bar --- admin/manage_users.php | 246 ++++++++++++++++++++--------------------- 1 file changed, 120 insertions(+), 126 deletions(-) diff --git a/admin/manage_users.php b/admin/manage_users.php index ca23bb26..bbdd29f1 100644 --- a/admin/manage_users.php +++ b/admin/manage_users.php @@ -164,149 +164,143 @@ require_once(HESK_PATH . 'inc/headerAdmin.inc.php'); require_once(HESK_PATH . 'inc/show_admin_nav.inc.php'); ?> -
      -
      -
      - -
      -
      -

      -
      *
      -
      - -
      -
      - -
      - -
      +
      +
      +
      +
      +
      *
      +
      + + +
      + +
      + +
      +
      +
      + +
      +
      -
      - -
      - -
      +
      +
      + +
      +
      -
      - -
      - -
      +
      +
      + +
      +
      -
      - -
      - -
      +
      +
      + +
      +
      -
      - -
      - -
      +
      +
      + +
      +
      +
      +
      +
      +
      +
      +
      + +
      + +
      +
      +
      +
      +
      - +
      -
      -
      -
      -
      + $catname) + { + echo '
      '; + } + ?>
      - +
      - -
      -
      - -
      -
      -
      -
      - -
      - $catname) - { - echo '
      '; - } - ?> -
      -
      -
      - -
      -
      '; + echo ' checked="checked" '; } - ?> -
      -
      -
      - -
      - -
      -
      - -
      -
      -
      - -
      - - -
      - - -
      -
      -
      -
      - - - - + echo ' />' . $hesklang[$k] . '
      '; + } + ?>
      +
      +
      + +
      + +
      +
      + +
      - - -
      -
      -
      +
      + +
      + + +
      + + +
      +
      +
      +
      + + + + +
      +
      + + +
      +
      -
      +
      -
      - -
      +
      + + + +
      + +
      +
      +
      +

      +
      +
      + +
      + +
      +
      +
      + +
      + /> +
      +
      +
      + + + +
      +
      +
      +
      + + +
      + +
      + +

      +
      + + + + + + + + + -

      -
      -
      - - - - - - - + /* Get number of tickets per category */ + $tickets_all = array(); + $tickets_total = 0; + + $res = hesk_dbQuery('SELECT COUNT(*) AS `cnt`, `category` FROM `'.hesk_dbEscape($hesk_settings['db_pfix']).'tickets` GROUP BY `category`'); + while ($tmp = hesk_dbFetchAssoc($res)) + { + $tickets_all[$tmp['category']] = $tmp['cnt']; + $tickets_total += $tmp['cnt']; + } - '; + } + else + { + $remove_code=' '; + } - if (isset($_SESSION['selcat2']) && $mycat['id'] == $_SESSION['selcat2']) + /* Is category private or public? */ + if ($mycat['type']) + { + $type_code = ''; + } + else + { + $type_code = ''; + } + + /* Is auto assign enabled? */ + if ($hesk_settings['autoassign']) + { + if ($mycat['autoassign']) { - $color = 'admin_green'; - unset($_SESSION['selcat2']); - } + $autoassign_code = ''; + } else { - $color = $i ? 'admin_white' : 'admin_gray'; + $autoassign_code = ''; } + } + else + { + $autoassign_code = ''; + } - $tmp = $i ? 'White' : 'Blue'; - $style = 'class="option'.$tmp.'OFF" onmouseover="this.className=\'option'.$tmp.'ON\'" onmouseout="this.className=\'option'.$tmp.'OFF\'"'; - $i = $i ? 0 : 1; - - /* Number of tickets and graph width */ - $all = isset($tickets_all[$mycat['id']]) ? $tickets_all[$mycat['id']] : 0; - $width_all = 0; - if ($tickets_total && $all) - { - $width_all = round(($all / $tickets_total) * 100); - } + echo ' + + + + + + + + '; - echo ' - - - - - - - - '; - - } // End while - - ?> -
      '.$mycat['id'].''.$mycat['name'].''.$all.' +
      +
      +
      +
      + + ' . $autoassign_code . ' + ' . $type_code . ' '; - /* Deleting category with ID 1 (default category) is not allowed */ - if ($mycat['id'] == 1) - { - $remove_code=' '; - } - else + if ($num > 1) + { + if ($j == 1) { - $remove_code=' '; + echo' '; } - - /* Is category private or public? */ - if ($mycat['type']) - { - $type_code = ''; - } - else - { - $type_code = ''; - } - - /* Is auto assign enabled? */ - if ($hesk_settings['autoassign']) + elseif ($j == $num) { - if ($mycat['autoassign']) - { - $autoassign_code = ''; - } - else - { - $autoassign_code = ''; - } + echo' '; } else { - $autoassign_code = ''; + echo' + +   + '; } + } + + echo $remove_code.'
      '.$mycat['id'].''.$mycat['name'].''.$all.' -
      -
      -
      -
      - - ' . $autoassign_code . ' - ' . $type_code . ' '; - - if ($num > 1) - { - if ($j == 1) - { - echo' '; - } - elseif ($j == $num) - { - echo' '; - } - else - { - echo' - -   - '; - } - } - - echo $remove_code.'
      -
      + } // End while + + ?> +
    +
    +.tabPadding { + padding: 10px; +} + @media (max-width:991px) { .close-ticket { text-align: left; From 4b0495fdd5466c9da63986e6784fb0936ce11b57 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sat, 9 Aug 2014 16:13:41 -0400 Subject: [PATCH 018/208] Now the managed canned responses page uses a panel --- admin/manage_canned.php | 348 ++++++++++++++++++++-------------------- 1 file changed, 172 insertions(+), 176 deletions(-) diff --git a/admin/manage_canned.php b/admin/manage_canned.php index 3c17af29..752d959b 100644 --- a/admin/manage_canned.php +++ b/admin/manage_canned.php @@ -107,202 +107,198 @@ myField.value += myValue; $j=0; $num = hesk_dbNumRows($result); ?> - -
    -
    -
    -
    - -
    -
    - +
    +
    +
    +
    + '.$hesklang['no_saved'].'

    '; + } + else + { ?> + + + + + + '.$hesklang['no_saved'].'

    '; - } - else - { ?> -
    - - - - - '.$mysaved['title'].''; - - - $javascript_messages.='myMsgTxt['.$mysaved['id'].']=\''.str_replace("\r\n","\\r\\n' + \r\n'", addslashes($mysaved['message']) )."';\n"; - $javascript_titles.='myTitle['.$mysaved['id'].']=\''.addslashes($mysaved['title'])."';\n"; - - echo ' - - - + + - - '; - } // End while - } - ?> -
    '.$mysaved['title'].' - '; - - if ($num > 1) + $color = 'admin_green'; + unset($_SESSION['canned']['selcat2']); + } + else + { + $color = $i ? 'admin_white' : 'admin_gray'; + } + + $tmp = $i ? 'White' : 'Blue'; + $style = 'class="option'.$tmp.'OFF" onmouseover="this.className=\'option'.$tmp.'ON\'" onmouseout="this.className=\'option'.$tmp.'OFF\'"'; + $i = $i ? 0 : 1; + + $options .= '
    '.$mysaved['title'].' + '; + + if ($num > 1) + { + if ($j == 1) { - if ($j == 1) - { - echo' '; - } - elseif ($j == $num) - { - echo' '; - } - else - { - echo' - - - '; - } + echo' '; + } + elseif ($j == $num) + { + echo' '; } else { - echo ''; + echo' + + + '; } + } + else + { + echo ''; + } - echo ' -  
    -
    -
    + echo ' +   + + '; + } // End while + } + ?> +
    -
    - - - -

    + } + //--> + + + +

    +
    + +
    +

    - - -

    -
    -
    -
    - 0) - { - ?> -
    +
    +
    + 0) + { + ?> +
    +
    -
    -
    -
    - : -
    -
    -
    - +
    +
    +
    +
    + :
    - '; - } - ?> -
    -
    -
    - -
    - /> -
    +
    + +
    +
    + '; + } + ?>
    -
    - -
    - - - : - | - - $v) - { - if ($v['use']) - { - echo '| '.$v['name'].' '; - } - } - ?> - -
    +
    +
    + +
    + />
    -
    - - -
    - -
    +
    +
    + +
    + + + : + | + + $v) + { + if ($v['use']) + { + echo '| '.$v['name'].' '; + } + } + ?> + +
    +
    +
    + + +
    +
    +
    Date: Sat, 9 Aug 2014 16:22:58 -0400 Subject: [PATCH 019/208] Knowledgebase page now uses a panel instead of tabbed bar --- admin/manage_knowledgebase.php | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/admin/manage_knowledgebase.php b/admin/manage_knowledgebase.php index e8aac0d1..e2c18228 100644 --- a/admin/manage_knowledgebase.php +++ b/admin/manage_knowledgebase.php @@ -1582,14 +1582,11 @@ function manage_category() {
    -
    -
    - -
    -
    +
    +
    +
    +
    +
    @@ -1629,7 +1626,9 @@ function manage_category() {
    - + + +
    From 9078b6b2ea0fc1b7874942d76d08d710cdfb002a Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sat, 9 Aug 2014 19:46:36 -0400 Subject: [PATCH 020/208] Now the reports page uses a panel instead of a tabbed container --- admin/reports.php | 1161 +++++++++++++++++++++++---------------------- 1 file changed, 581 insertions(+), 580 deletions(-) diff --git a/admin/reports.php b/admin/reports.php index 226017b2..917b4134 100644 --- a/admin/reports.php +++ b/admin/reports.php @@ -228,628 +228,629 @@ require_once(HESK_PATH . 'inc/headerAdmin.inc.php'); require_once(HESK_PATH . 'inc/show_admin_nav.inc.php'); ?> -
    -
    -
    -
    - -
    -
    -
    -
    - -
    - /> - -
    -
    - /> - - -
    -
    -
    - - -
    -
    - - -
    -
    -
    -
    -
    -
    -
    +
    +
    +
    +
    + +
    + +
    > + ' . $hesklang['export'] . '
    '; + } + ?> +
    +
    + +
    + /> + +
    +
    + /> + + +
    +
    +
    + + +
    +
    + + +
    +
    +
    +
    +
    +
    + + + +

    +
    - +

    -

    +
    {$hesklang['roo']}

    "; + } + + /* Report type */ + switch ($type) + { + case 2: + hesk_ticketsByMonth(); + break; + case 3: + hesk_ticketsByUser(); + break; + case 4: + hesk_ticketsByCategory(); + break; + default: + hesk_ticketsByDay(); + } + + require_once(HESK_PATH . 'inc/footer.inc.php'); + exit(); + + + /*** START FUNCTIONS ***/ + + + function hesk_ticketsByCategory() + { + global $hesk_settings, $hesklang, $date_from, $date_to, $can_run_reports_full; + + /* List of categories */ + $cat = array(); + $res = hesk_dbQuery("SELECT `id`,`name` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."categories` WHERE " . ( $can_run_reports_full ? '1' : hesk_myCategories('id') ) . " ORDER BY `id` ASC"); + while ($row=hesk_dbFetchAssoc($res)) { - ?> -

    -
    - 0, 'resolved' => 0, 'all_replies' => 0, 'staff_replies' => 0, 'worked' => 0); + + /* Populate category counts */ + foreach ($cat as $id => $name) { - ?> -

    -

    -
    - 0, + 'resolved' => 0, + 'all_replies' => 0, + 'staff_replies' => 0, + 'worked' => '', + ); } - // Show a note if reports are limited - if ( ! $can_run_reports_full) + /* SQL query for category stats */ + $res = hesk_dbQuery(" + SELECT DISTINCT `t1`.`category`, `t2`.`num_tickets`, `t2`.`seconds_worked` AS `seconds_worked`, IFNULL(`t3`.`all_replies`,0) AS `all_replies`, IFNULL(`t4`.`staff_replies`,0) AS `staff_replies` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` AS `t1` + LEFT JOIN (SELECT COUNT(*) AS `num_tickets`, SUM( TIME_TO_SEC(`time_worked`) ) AS `seconds_worked`, `category` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` AS `t1` WHERE DATE(`t1`.`dt`) BETWEEN '" . hesk_dbEscape($date_from) . "' AND '" . hesk_dbEscape($date_to) . "' " . ( $can_run_reports_full ? "" : " AND `t1`.`owner` = '" . intval($_SESSION['id']) . "'" ) . " GROUP BY `category`) AS `t2` ON `t1`.`category`=`t2`.`category` + LEFT JOIN (SELECT COUNT(*) AS `all_replies`, `t1`.`category` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` AS `t1`, `".hesk_dbEscape($hesk_settings['db_pfix'])."replies` AS `t5` WHERE `t1`.`id`=`t5`.`replyto` AND DATE(`t5`.`dt`) BETWEEN '" . hesk_dbEscape($date_from) . "' AND '" . hesk_dbEscape($date_to) . "' " . ( $can_run_reports_full ? "" : " AND `t1`.`owner` = '" . intval($_SESSION['id']) . "'" ) . " GROUP BY `t1`.`category`) AS `t3` ON `t1`.`category`=`t3`.`category` + LEFT JOIN (SELECT COUNT(*) AS `staff_replies`, `t1`.`category` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` AS `t1`, `".hesk_dbEscape($hesk_settings['db_pfix'])."replies` AS `t5` WHERE `t1`.`id`=`t5`.`replyto` AND " . ( $can_run_reports_full ? "`t5`.`staffid` > 0" : "`t5`.`staffid` = '" . intval($_SESSION['id']) . "'" ) . " AND DATE(`t5`.`dt`) BETWEEN '" . hesk_dbEscape($date_from) . "' AND '" . hesk_dbEscape($date_to) . "' GROUP BY `t1`.`category`) AS `t4` ON `t1`.`category`=`t4`.`category` + WHERE DATE(`t1`.`dt`) BETWEEN '" . hesk_dbEscape($date_from) . "' AND '" . hesk_dbEscape($date_to) . "'" . + ( $can_run_reports_full ? "" : " AND `t1`.`owner` = '" . intval($_SESSION['id']) . "'" ) + ); + + /* Update ticket values */ + while ($row = hesk_dbFetchAssoc($res)) { - echo "

    {$hesklang['roo']}

    "; + if (isset($cat[$row['category']])) + { + $tickets[$row['category']]['num_tickets'] += $row['num_tickets']; + $tickets[$row['category']]['all_replies'] += $row['all_replies']; + $tickets[$row['category']]['staff_replies'] += $row['staff_replies']; + $tickets[$row['category']]['worked'] = hesk_SecondsToHHMMSS($row['seconds_worked']); + } + else + { + /* Category deleted */ + if ( ! isset($tickets[9999]) ) + { + $cat[9999] = $hesklang['catd']; + $tickets[9999] = array('num_tickets' => $row['num_tickets'], 'resolved' => 0, 'all_replies' => $row['all_replies'], 'staff_replies' => $row['staff_replies'], 'worked' => $row['seconds_worked']); + } + else + { + $tickets[9999]['num_tickets'] += $row['num_tickets']; + $tickets[9999]['all_replies'] += $row['all_replies']; + $tickets[9999]['staff_replies'] += $row['staff_replies']; + $tickets[9999]['worked'] += $row['seconds_worked']; + } + } + + $totals['num_tickets'] += $row['num_tickets']; + $totals['all_replies'] += $row['all_replies']; + $totals['staff_replies'] += $row['staff_replies']; + $totals['worked'] += $row['seconds_worked']; } - /* Report type */ - switch ($type) + // Get number of resolved tickets + $res = hesk_dbQuery("SELECT COUNT(*) AS `num_tickets` , `category` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` WHERE `status` IN (SELECT `ID` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."statuses` WHERE `IsClosed` = 1) " . ( $can_run_reports_full ? "" : " AND `owner` = '" . intval($_SESSION['id']) . "'" ) . " AND DATE(`dt`) BETWEEN '" . hesk_dbEscape($date_from) . "' AND '" . hesk_dbEscape($date_to) . "' GROUP BY `category`"); + + // Update number of open and resolved tickets + while ($row = hesk_dbFetchAssoc($res)) { - case 2: - hesk_ticketsByMonth(); - break; - case 3: - hesk_ticketsByUser(); - break; - case 4: - hesk_ticketsByCategory(); - break; - default: - hesk_ticketsByDay(); + if (isset($cat[$row['category']])) + { + $tickets[$row['category']]['resolved'] += $row['num_tickets']; + } + else + { + // Category deleted + $tickets[9999]['resolved'] += $row['num_tickets']; + } + + $totals['resolved'] += $row['num_tickets']; } - require_once(HESK_PATH . 'inc/footer.inc.php'); - exit(); + // Convert total seconds worked to HH:MM:SS + $totals['worked'] = hesk_SecondsToHHMMSS($totals['worked']); + if ( isset($tickets[9999]) ) + { + $tickets[9999]['worked'] = hesk_SecondsToHHMMSS($tickets[9999]['worked']); + } + ?> + + + + + + + + + + - /*** START FUNCTIONS ***/ + 10) + { + ?> + + + + + + + + + + $d) { - global $hesk_settings, $hesklang, $date_from, $date_to, $can_run_reports_full; - /* List of categories */ - $cat = array(); - $res = hesk_dbQuery("SELECT `id`,`name` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."categories` WHERE " . ( $can_run_reports_full ? '1' : hesk_myCategories('id') ) . " ORDER BY `id` ASC"); - while ($row=hesk_dbFetchAssoc($res)) - { - $cat[$row['id']]=$row['name']; - } + ?> + + + + + + + + + + + + + + + + + + + +
    + 0, 'resolved' => 0, 'tickets' => 0, 'replies' => 0, 'worked' => 0); - $tickets = array(); - $totals = array('num_tickets' => 0, 'resolved' => 0, 'all_replies' => 0, 'staff_replies' => 0, 'worked' => 0); + // Get list of users + $admins = array(); - /* Populate category counts */ - foreach ($cat as $id => $name) + // I. ADMINISTRATORS can view all users + if ($_SESSION['isadmin'] || hesk_checkPermission('can_run_reports_full', 0) ) + { + // -> get list of users + $res = hesk_dbQuery("SELECT `id`,`name` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."users` ORDER BY `id` ASC"); + + // -> populate $admins and $tickets arrays + while ($row=hesk_dbFetchAssoc($res)) { - $tickets[$id] = array( - 'num_tickets' => 0, - 'resolved' => 0, - 'all_replies' => 0, - 'staff_replies' => 0, - 'worked' => '', + $admins[$row['id']] = $row['name']; + + $tickets[$row['id']] = array( + 'asstickets' => 0, + 'resolved' => 0, + 'tickets' => 0, + 'replies' => 0, + 'worked' => '', ); } - /* SQL query for category stats */ - $res = hesk_dbQuery(" - SELECT DISTINCT `t1`.`category`, `t2`.`num_tickets`, `t2`.`seconds_worked` AS `seconds_worked`, IFNULL(`t3`.`all_replies`,0) AS `all_replies`, IFNULL(`t4`.`staff_replies`,0) AS `staff_replies` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` AS `t1` - LEFT JOIN (SELECT COUNT(*) AS `num_tickets`, SUM( TIME_TO_SEC(`time_worked`) ) AS `seconds_worked`, `category` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` AS `t1` WHERE DATE(`t1`.`dt`) BETWEEN '" . hesk_dbEscape($date_from) . "' AND '" . hesk_dbEscape($date_to) . "' " . ( $can_run_reports_full ? "" : " AND `t1`.`owner` = '" . intval($_SESSION['id']) . "'" ) . " GROUP BY `category`) AS `t2` ON `t1`.`category`=`t2`.`category` - LEFT JOIN (SELECT COUNT(*) AS `all_replies`, `t1`.`category` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` AS `t1`, `".hesk_dbEscape($hesk_settings['db_pfix'])."replies` AS `t5` WHERE `t1`.`id`=`t5`.`replyto` AND DATE(`t5`.`dt`) BETWEEN '" . hesk_dbEscape($date_from) . "' AND '" . hesk_dbEscape($date_to) . "' " . ( $can_run_reports_full ? "" : " AND `t1`.`owner` = '" . intval($_SESSION['id']) . "'" ) . " GROUP BY `t1`.`category`) AS `t3` ON `t1`.`category`=`t3`.`category` - LEFT JOIN (SELECT COUNT(*) AS `staff_replies`, `t1`.`category` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` AS `t1`, `".hesk_dbEscape($hesk_settings['db_pfix'])."replies` AS `t5` WHERE `t1`.`id`=`t5`.`replyto` AND " . ( $can_run_reports_full ? "`t5`.`staffid` > 0" : "`t5`.`staffid` = '" . intval($_SESSION['id']) . "'" ) . " AND DATE(`t5`.`dt`) BETWEEN '" . hesk_dbEscape($date_from) . "' AND '" . hesk_dbEscape($date_to) . "' GROUP BY `t1`.`category`) AS `t4` ON `t1`.`category`=`t4`.`category` - WHERE DATE(`t1`.`dt`) BETWEEN '" . hesk_dbEscape($date_from) . "' AND '" . hesk_dbEscape($date_to) . "'" . - ( $can_run_reports_full ? "" : " AND `t1`.`owner` = '" . intval($_SESSION['id']) . "'" ) - ); + // -> get list of tickets + $res = hesk_dbQuery("SELECT `owner`, COUNT(*) AS `cnt`, SUM( TIME_TO_SEC(`time_worked`) ) AS `seconds_worked` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` WHERE `owner` IN ('" . implode("','", array_keys($admins) ) . "') AND DATE(`dt`) BETWEEN '" . hesk_dbEscape($date_from) . "' AND '" . hesk_dbEscape($date_to) . "' GROUP BY `owner`"); - /* Update ticket values */ - while ($row = hesk_dbFetchAssoc($res)) - { - if (isset($cat[$row['category']])) - { - $tickets[$row['category']]['num_tickets'] += $row['num_tickets']; - $tickets[$row['category']]['all_replies'] += $row['all_replies']; - $tickets[$row['category']]['staff_replies'] += $row['staff_replies']; - $tickets[$row['category']]['worked'] = hesk_SecondsToHHMMSS($row['seconds_worked']); - } - else - { - /* Category deleted */ - if ( ! isset($tickets[9999]) ) - { - $cat[9999] = $hesklang['catd']; - $tickets[9999] = array('num_tickets' => $row['num_tickets'], 'resolved' => 0, 'all_replies' => $row['all_replies'], 'staff_replies' => $row['staff_replies'], 'worked' => $row['seconds_worked']); - } - else - { - $tickets[9999]['num_tickets'] += $row['num_tickets']; - $tickets[9999]['all_replies'] += $row['all_replies']; - $tickets[9999]['staff_replies'] += $row['staff_replies']; - $tickets[9999]['worked'] += $row['seconds_worked']; - } - } + // -> update ticket list values + while ($row = hesk_dbFetchAssoc($res)) + { + $tickets[$row['owner']]['asstickets'] += $row['cnt']; + $totals['asstickets'] += $row['cnt']; + $tickets[$row['owner']]['worked'] = hesk_SecondsToHHMMSS($row['seconds_worked']); + $totals['worked'] += $row['seconds_worked']; + } - $totals['num_tickets'] += $row['num_tickets']; - $totals['all_replies'] += $row['all_replies']; - $totals['staff_replies'] += $row['staff_replies']; - $totals['worked'] += $row['seconds_worked']; - } + // -> get list of resolved tickets + $res = hesk_dbQuery("SELECT `owner`, COUNT(*) AS `cnt` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` WHERE `owner` IN ('" . implode("','", array_keys($admins) ) . "') AND `status` IN (SELECT `ID` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."statuses` WHERE `IsClosed` = 1) AND DATE(`dt`) BETWEEN '" . hesk_dbEscape($date_from) . "' AND '" . hesk_dbEscape($date_to) . "' GROUP BY `owner`"); - // Get number of resolved tickets - $res = hesk_dbQuery("SELECT COUNT(*) AS `num_tickets` , `category` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` WHERE `status` IN (SELECT `ID` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."statuses` WHERE `IsClosed` = 1) " . ( $can_run_reports_full ? "" : " AND `owner` = '" . intval($_SESSION['id']) . "'" ) . " AND DATE(`dt`) BETWEEN '" . hesk_dbEscape($date_from) . "' AND '" . hesk_dbEscape($date_to) . "' GROUP BY `category`"); + // -> update resolved ticket list values + while ($row = hesk_dbFetchAssoc($res)) + { + $tickets[$row['owner']]['resolved'] += $row['cnt']; + $totals['resolved'] += $row['cnt']; + } - // Update number of open and resolved tickets - while ($row = hesk_dbFetchAssoc($res)) - { - if (isset($cat[$row['category']])) - { - $tickets[$row['category']]['resolved'] += $row['num_tickets']; - } - else - { - // Category deleted - $tickets[9999]['resolved'] += $row['num_tickets']; - } + // -> get number of replies + $res = hesk_dbQuery("SELECT `staffid`, COUNT(*) AS `cnt`, COUNT(DISTINCT `replyto`) AS `tcnt` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."replies` WHERE `staffid` IN ('" . implode("','", array_keys($admins) ) . "') AND DATE(`dt`) BETWEEN '" . hesk_dbEscape($date_from) . "' AND '" . hesk_dbEscape($date_to) . "' GROUP BY `staffid`"); - $totals['resolved'] += $row['num_tickets']; - } - - // Convert total seconds worked to HH:MM:SS - $totals['worked'] = hesk_SecondsToHHMMSS($totals['worked']); - if ( isset($tickets[9999]) ) - { - $tickets[9999]['worked'] = hesk_SecondsToHHMMSS($tickets[9999]['worked']); - } - - ?> - - - - - - - - - - - - 10) - { - ?> - - - - - - - - - - $d) - { - - ?> - - - - - - - - - - - - - - - - - - - -
    - update number of replies values + while ($row = hesk_dbFetchAssoc($res)) + { + $tickets[$row['staffid']]['tickets'] += $row['tcnt']; + $tickets[$row['staffid']]['replies'] += $row['cnt']; + + $totals['tickets'] += $row['tcnt']; + $totals['replies'] += $row['cnt']; + } + } + // II. OTHER STAFF may only see their own stats + else + { + $admins[$_SESSION['id']] = $_SESSION['name']; + + // -> get list of tickets + $res = hesk_dbQuery("SELECT COUNT(*) AS `cnt`, SUM( TIME_TO_SEC(`time_worked`) ) AS `seconds_worked` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` WHERE `owner` = '" . intval($_SESSION['id']) . "' AND DATE(`dt`) BETWEEN '" . hesk_dbEscape($date_from) . "' AND '" . hesk_dbEscape($date_to) . "'"); + $row = hesk_dbFetchAssoc($res); + + // -> update ticket values + $tickets[$_SESSION['id']]['asstickets'] = $row['cnt']; + $totals['asstickets'] = $row['cnt']; + $tickets[$_SESSION['id']]['worked'] = hesk_SecondsToHHMMSS($row['seconds_worked']); + $totals['worked'] += $row['seconds_worked']; + + // -> get list of resolved tickets + $res = hesk_dbQuery("SELECT COUNT(*) AS `cnt` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` WHERE `owner` = '" . intval($_SESSION['id']) . "' AND `status`='3' AND DATE(`dt`) BETWEEN '" . hesk_dbEscape($date_from) . "' AND '" . hesk_dbEscape($date_to) . "'"); + $row = hesk_dbFetchAssoc($res); + + // -> update resolved ticket values + $tickets[$_SESSION['id']]['resolved'] = $row['cnt']; + $totals['resolved'] = $row['cnt']; + + // -> get number of replies + $res = hesk_dbQuery("SELECT COUNT(*) AS `cnt`, COUNT(DISTINCT `replyto`) AS `tcnt` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."replies` WHERE `staffid` = '" . intval($_SESSION['id']) . "' AND DATE(`dt`) BETWEEN '" . hesk_dbEscape($date_from) . "' AND '" . hesk_dbEscape($date_to) . "'"); + $row = hesk_dbFetchAssoc($res); + + $tickets[$_SESSION['id']]['tickets'] = $row['tcnt']; + $tickets[$_SESSION['id']]['replies'] = $row['cnt']; + $totals['tickets'] = $row['tcnt']; + $totals['replies'] = $row['cnt']; - function hesk_ticketsByUser() + } + + // Convert total seconds worked to HH:MM:SS + $totals['worked'] = hesk_SecondsToHHMMSS($totals['worked']); + + ?> + + + + + + + + + + + + 10) + { + ?> + + + + + + + + + + $d) { - global $hesk_settings, $hesklang, $date_from, $date_to; - - // Some variables we will need - $tickets = array(); - $totals = array('asstickets' => 0, 'resolved' => 0, 'tickets' => 0, 'replies' => 0, 'worked' => 0); - - // Get list of users - $admins = array(); - - // I. ADMINISTRATORS can view all users - if ($_SESSION['isadmin'] || hesk_checkPermission('can_run_reports_full', 0) ) - { - // -> get list of users - $res = hesk_dbQuery("SELECT `id`,`name` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."users` ORDER BY `id` ASC"); - - // -> populate $admins and $tickets arrays - while ($row=hesk_dbFetchAssoc($res)) - { - $admins[$row['id']] = $row['name']; - - $tickets[$row['id']] = array( - 'asstickets' => 0, - 'resolved' => 0, - 'tickets' => 0, - 'replies' => 0, - 'worked' => '', - ); - } - - // -> get list of tickets - $res = hesk_dbQuery("SELECT `owner`, COUNT(*) AS `cnt`, SUM( TIME_TO_SEC(`time_worked`) ) AS `seconds_worked` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` WHERE `owner` IN ('" . implode("','", array_keys($admins) ) . "') AND DATE(`dt`) BETWEEN '" . hesk_dbEscape($date_from) . "' AND '" . hesk_dbEscape($date_to) . "' GROUP BY `owner`"); - - // -> update ticket list values - while ($row = hesk_dbFetchAssoc($res)) - { - $tickets[$row['owner']]['asstickets'] += $row['cnt']; - $totals['asstickets'] += $row['cnt']; - $tickets[$row['owner']]['worked'] = hesk_SecondsToHHMMSS($row['seconds_worked']); - $totals['worked'] += $row['seconds_worked']; - } - - // -> get list of resolved tickets - $res = hesk_dbQuery("SELECT `owner`, COUNT(*) AS `cnt` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` WHERE `owner` IN ('" . implode("','", array_keys($admins) ) . "') AND `status` IN (SELECT `ID` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."statuses` WHERE `IsClosed` = 1) AND DATE(`dt`) BETWEEN '" . hesk_dbEscape($date_from) . "' AND '" . hesk_dbEscape($date_to) . "' GROUP BY `owner`"); - - // -> update resolved ticket list values - while ($row = hesk_dbFetchAssoc($res)) - { - $tickets[$row['owner']]['resolved'] += $row['cnt']; - $totals['resolved'] += $row['cnt']; - } - - // -> get number of replies - $res = hesk_dbQuery("SELECT `staffid`, COUNT(*) AS `cnt`, COUNT(DISTINCT `replyto`) AS `tcnt` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."replies` WHERE `staffid` IN ('" . implode("','", array_keys($admins) ) . "') AND DATE(`dt`) BETWEEN '" . hesk_dbEscape($date_from) . "' AND '" . hesk_dbEscape($date_to) . "' GROUP BY `staffid`"); - - // -> update number of replies values - while ($row = hesk_dbFetchAssoc($res)) - { - $tickets[$row['staffid']]['tickets'] += $row['tcnt']; - $tickets[$row['staffid']]['replies'] += $row['cnt']; - - $totals['tickets'] += $row['tcnt']; - $totals['replies'] += $row['cnt']; - } - } - // II. OTHER STAFF may only see their own stats - else - { - $admins[$_SESSION['id']] = $_SESSION['name']; - - // -> get list of tickets - $res = hesk_dbQuery("SELECT COUNT(*) AS `cnt`, SUM( TIME_TO_SEC(`time_worked`) ) AS `seconds_worked` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` WHERE `owner` = '" . intval($_SESSION['id']) . "' AND DATE(`dt`) BETWEEN '" . hesk_dbEscape($date_from) . "' AND '" . hesk_dbEscape($date_to) . "'"); - $row = hesk_dbFetchAssoc($res); - - // -> update ticket values - $tickets[$_SESSION['id']]['asstickets'] = $row['cnt']; - $totals['asstickets'] = $row['cnt']; - $tickets[$_SESSION['id']]['worked'] = hesk_SecondsToHHMMSS($row['seconds_worked']); - $totals['worked'] += $row['seconds_worked']; - - // -> get list of resolved tickets - $res = hesk_dbQuery("SELECT COUNT(*) AS `cnt` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` WHERE `owner` = '" . intval($_SESSION['id']) . "' AND `status`='3' AND DATE(`dt`) BETWEEN '" . hesk_dbEscape($date_from) . "' AND '" . hesk_dbEscape($date_to) . "'"); - $row = hesk_dbFetchAssoc($res); - - // -> update resolved ticket values - $tickets[$_SESSION['id']]['resolved'] = $row['cnt']; - $totals['resolved'] = $row['cnt']; - - // -> get number of replies - $res = hesk_dbQuery("SELECT COUNT(*) AS `cnt`, COUNT(DISTINCT `replyto`) AS `tcnt` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."replies` WHERE `staffid` = '" . intval($_SESSION['id']) . "' AND DATE(`dt`) BETWEEN '" . hesk_dbEscape($date_from) . "' AND '" . hesk_dbEscape($date_to) . "'"); - $row = hesk_dbFetchAssoc($res); - - $tickets[$_SESSION['id']]['tickets'] = $row['tcnt']; - $tickets[$_SESSION['id']]['replies'] = $row['cnt']; - - $totals['tickets'] = $row['tcnt']; - $totals['replies'] = $row['cnt']; - - } - - // Convert total seconds worked to HH:MM:SS - $totals['worked'] = hesk_SecondsToHHMMSS($totals['worked']); - - ?> -
    - - - - - - - - - - - 10) - { - ?> - - - - - - - - - - $d) - { - - ?> - - - - - - - - - - - - - - - - - - - -
    + + ?> + + + + + + + + + + + + + + + + + + + + 0, 'resolved' => 0, 'worked' => 0); + $dt = MonthsArray($date_from,$date_to); + + // Pre-populate date values + foreach ($dt as $month) { - global $hesk_settings, $hesklang, $date_from, $date_to, $can_run_reports_full; - - $tickets = array(); - $totals = array('all' => 0, 'resolved' => 0, 'worked' => 0); - $dt = MonthsArray($date_from,$date_to); - - // Pre-populate date values - foreach ($dt as $month) - { - $tickets[$month] = array( - 'all' => 0, - 'resolved' => 0, - 'worked' => '', - ); - } - - // SQL query for all - $res = hesk_dbQuery("SELECT YEAR(`dt`) AS `myyear`, MONTH(`dt`) AS `mymonth`, COUNT(*) AS `cnt`, SUM( TIME_TO_SEC(`time_worked`) ) AS `seconds_worked` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` WHERE " . ( $can_run_reports_full ? '1' : "`owner` = '" . intval($_SESSION['id']) . "'" ) . " AND DATE(`dt`) BETWEEN '" . hesk_dbEscape($date_from) . "' AND '" . hesk_dbEscape($date_to) . "' GROUP BY `myyear`,`mymonth`"); - - // Update ticket values - while ($row = hesk_dbFetchAssoc($res)) - { - $row['mymonth'] = sprintf('%02d',$row['mymonth']); - $tickets[$row['myyear'].'-'.$row['mymonth'].'-01']['all'] += $row['cnt']; - $tickets[$row['myyear'].'-'.$row['mymonth'].'-01']['worked'] = hesk_SecondsToHHMMSS($row['seconds_worked']); - $totals['all'] += $row['cnt']; - $totals['worked'] += $row['seconds_worked']; - } - - // SQL query for resolved - $res = hesk_dbQuery("SELECT YEAR(`dt`) AS `myyear`, MONTH(`dt`) AS `mymonth`, COUNT(*) AS `cnt` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` WHERE " . ( $can_run_reports_full ? '1' : "`owner` = '" . intval($_SESSION['id']) . "'" ) . " AND `status` = '3' AND DATE(`dt`) BETWEEN '" . hesk_dbEscape($date_from) . "' AND '" . hesk_dbEscape($date_to) . "' GROUP BY `myyear`,`mymonth`"); - - // Update ticket values - while ($row = hesk_dbFetchAssoc($res)) - { - $row['mymonth'] = sprintf('%02d',$row['mymonth']); - $tickets[$row['myyear'].'-'.$row['mymonth'].'-01']['resolved'] += $row['cnt']; - $totals['resolved'] += $row['cnt']; - } - - // Convert total seconds worked to HH:MM:SS - $totals['worked'] = hesk_SecondsToHHMMSS($totals['worked']); - - ?> - - - - - - - - - - 10) - { - ?> - - - - - - - - $d) - { - - ?> - - - - - - - - - - - - - - - -
    + $tickets[$month] = array( + 'all' => 0, + 'resolved' => 0, + 'worked' => '', + ); + } - + + + + + + + + + + 10) + { + ?> + + + + + + + + $d) { - global $hesk_settings, $hesklang, $date_from, $date_to, $can_run_reports_full; - - $tickets = array(); - $totals = array('all' => 0, 'resolved' => 0, 'worked' => 0); - $dt = DateArray($date_from,$date_to); - - // Pre-populate date values - foreach ($dt as $day) - { - $tickets[$day] = array( - 'all' => 0, - 'resolved' => 0, - 'worked' => '', - ); - } - - // SQL query for all - $res = hesk_dbQuery("SELECT DATE(`dt`) AS `mydt`, COUNT(*) AS `cnt`, SUM( TIME_TO_SEC(`time_worked`) ) AS `seconds_worked` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` WHERE " . ( $can_run_reports_full ? '1' : "`owner` = '" . intval($_SESSION['id']) . "'" ) . " AND DATE(`dt`) BETWEEN '" . hesk_dbEscape($date_from) . "' AND '" . hesk_dbEscape($date_to) . "' GROUP BY `mydt`"); - - // Update ticket values - while ($row = hesk_dbFetchAssoc($res)) - { - $tickets[$row['mydt']]['all'] += $row['cnt']; - $tickets[$row['mydt']]['worked'] = hesk_SecondsToHHMMSS($row['seconds_worked']); - $totals['all'] += $row['cnt']; - $totals['worked'] += $row['seconds_worked']; - } - - // SQL query for resolved - $res = hesk_dbQuery("SELECT DATE(`dt`) AS `mydt`, COUNT(*) AS `cnt` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` WHERE " . ( $can_run_reports_full ? '1' : "`owner` = '" . intval($_SESSION['id']) . "'" ) . " AND `status` IN (SELECT `ID` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."statuses` WHERE `IsClosed` = 1) AND DATE(`dt`) BETWEEN '" . hesk_dbEscape($date_from) . "' AND '" . hesk_dbEscape($date_to) . "' GROUP BY `mydt`"); - - // Update ticket values - while ($row = hesk_dbFetchAssoc($res)) - { - $tickets[$row['mydt']]['resolved'] += $row['cnt']; - $totals['resolved'] += $row['cnt']; - } - - // Convert total seconds worked to HH:MM:SS - $totals['worked'] = hesk_SecondsToHHMMSS($totals['worked']); - - ?> -
    - - - - - - - - - 10) - { - ?> - - - - - - - - $d) - { - - ?> - - - - - - - - - - - - - - - -
    + + ?> + + + + + + + -
    -
    -
    + } + ?> + + + + + + + + + + 0, 'resolved' => 0, 'worked' => 0); + $dt = DateArray($date_from,$date_to); + // Pre-populate date values + foreach ($dt as $day) + { + $tickets[$day] = array( + 'all' => 0, + 'resolved' => 0, + 'worked' => '', + ); + } + // SQL query for all + $res = hesk_dbQuery("SELECT DATE(`dt`) AS `mydt`, COUNT(*) AS `cnt`, SUM( TIME_TO_SEC(`time_worked`) ) AS `seconds_worked` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` WHERE " . ( $can_run_reports_full ? '1' : "`owner` = '" . intval($_SESSION['id']) . "'" ) . " AND DATE(`dt`) BETWEEN '" . hesk_dbEscape($date_from) . "' AND '" . hesk_dbEscape($date_to) . "' GROUP BY `mydt`"); + + // Update ticket values + while ($row = hesk_dbFetchAssoc($res)) + { + $tickets[$row['mydt']]['all'] += $row['cnt']; + $tickets[$row['mydt']]['worked'] = hesk_SecondsToHHMMSS($row['seconds_worked']); + $totals['all'] += $row['cnt']; + $totals['worked'] += $row['seconds_worked']; + } + + // SQL query for resolved + $res = hesk_dbQuery("SELECT DATE(`dt`) AS `mydt`, COUNT(*) AS `cnt` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` WHERE " . ( $can_run_reports_full ? '1' : "`owner` = '" . intval($_SESSION['id']) . "'" ) . " AND `status` IN (SELECT `ID` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."statuses` WHERE `IsClosed` = 1) AND DATE(`dt`) BETWEEN '" . hesk_dbEscape($date_from) . "' AND '" . hesk_dbEscape($date_to) . "' GROUP BY `mydt`"); + + // Update ticket values + while ($row = hesk_dbFetchAssoc($res)) + { + $tickets[$row['mydt']]['resolved'] += $row['cnt']; + $totals['resolved'] += $row['cnt']; + } + + // Convert total seconds worked to HH:MM:SS + $totals['worked'] = hesk_SecondsToHHMMSS($totals['worked']); + + ?> + + + + + + + + + + 10) + { + ?> + + + + + + + + $d) + { + + ?> + + + + + + + + + + + + + + + +
    + +
    +
    \ No newline at end of file From 20299319740e83f6837af5af0d74c94dca266eb0 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sat, 9 Aug 2014 19:52:35 -0400 Subject: [PATCH 021/208] Now the export page uses a panel instead of a tabbed menu --- admin/export.php | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/admin/export.php b/admin/export.php index f497428a..4be220ef 100644 --- a/admin/export.php +++ b/admin/export.php @@ -701,25 +701,22 @@ require_once(HESK_PATH . 'inc/headerAdmin.inc.php'); require_once(HESK_PATH . 'inc/show_admin_nav.inc.php'); ?> -
    -
    -
    -
    - -
    -
    -

    -
    -
    -
    +
    +
    +
    +
    + + +
    Date: Sat, 9 Aug 2014 20:29:21 -0400 Subject: [PATCH 022/208] Status section is now a panel, and padded tabbed sections --- admin/admin_settings.php | 3217 +++++++++++++++++++------------------- 1 file changed, 1606 insertions(+), 1611 deletions(-) diff --git a/admin/admin_settings.php b/admin/admin_settings.php index 67e9c50c..1f37ca6d 100644 --- a/admin/admin_settings.php +++ b/admin/admin_settings.php @@ -97,814 +97,761 @@ if ( defined('HESK_DEMO') ) ?> -
    -
    -
    -
    - -
    -
    - - - - - - - - - - - - - - - - -
    - : - - - ' . $hesklang['hud'] . ' '; - } - elseif ($latest != -1) - { - // Is this a beta/dev version? - if ( strpos($hesk_settings['hesk_version'], 'beta') || strpos($hesk_settings['hesk_version'], 'dev') ) - { - echo ' ' . $hesklang['beta'] . ' '; ?> ' . $hesklang['hnw'] . ' '; ?> - - -
    - : - - -
    - : - - -
    - /hesk_settings.inc.php - - '.$hesklang['exists'].', '.$hesklang['writable'].''; - } else { - echo ''.$hesklang['exists'].', '.$hesklang['not_writable'].'
    '.$hesklang['e_settings']; - } - ?> -
    - / - - '.$hesklang['exists'].', '; - if (is_writable(HESK_PATH . $hesk_settings['attach_dir'])) - { - $enable_use_attachments=1; - echo ''.$hesklang['writable'].''; - } - else - { - echo ''.$hesklang['not_writable'].'
    '.$hesklang['e_attdir']; - } - } - else - { - echo ''.$hesklang['no_exists'].', '.$hesklang['not_writable'].'
    '.$hesklang['e_attdir']; - } - ?> -
    -
    -
    -
    -
    -
    - =') && @ini_get('max_file_uploads') && @ini_get('max_file_uploads') < $hesk_settings['attachments']['max_number'] ) - { - hesk_show_notice($hesklang['fatte1']); - } - - // Check max attachment size - $tmp = @ini_get('upload_max_filesize'); - if ($tmp) - { - $last = strtoupper(substr($tmp,-1)); - - switch ($last) - { - case 'K': - $tmp = $tmp * 1024; - break; - case 'M': - $tmp = $tmp * 1048576; - break; - case 'G': - $tmp = $tmp * 1073741824; - break; - default: - $tmp = $tmp; - } - - if ($tmp < $hesk_settings['attachments']['max_size']) - { - hesk_show_notice($hesklang['fatte2']); - } - } - - // Check max post size - $tmp = @ini_get('post_max_size'); - if ($tmp) - { - $last = strtoupper(substr($tmp,-1)); - - switch ($last) - { - case 'K': - $tmp = $tmp * 1024; - break; - case 'M': - $tmp = $tmp * 1048576; - break; - case 'G': - $tmp = $tmp * 1073741824; - break; - default: - $tmp = $tmp; - } - - if ($tmp < ( $hesk_settings['attachments']['max_size'] * $hesk_settings['attachments']['max_number'] + 524288 ) ) - { - hesk_show_notice($hesklang['fatte3']); - } - } - } - - - $hesklang['err_custname'] = addslashes($hesklang['err_custname']); +
    +
    +
    +
    +
    + + + - -
    + : + + + - - -

    -
    - -
    - - - - -
    - -
    -
    -
    - -
    - -
    - -
    -
    -
    - -
    - -
    -
    -
    - -
    - -
    -
    -
    - -
    - -
    + return i; + } + //--> + + +

    +
    + + + + + + +
    + +
    +
    +
    + +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    + +
    +
    +
    + +
    + +   +
    -
    - -
    - -
    +
    +
    + +
    +
    +
    '; + ?>
    +
    -
    -
    -
    - -
    - -   - -
    -
    -
    - -
    -
    -
    '; - ?> -
    +
    +
    + +
    + +
    +
    - -
    -
    - -
    - -
    - -
    +
    +
    + +
    +
    -
    - -
    - -
    +
    +
    + +
    +
    -
    - -
    - -
    +
    +
    + +
    +
    -
    - -
    - -
    +
    +
    + +
    +
    -
    - -
    - +
    +
    +
    + + + -
    -
    -
    - - - - - -
    -
    -
    - - -
    -
    -
    - -
    - -
    - -
    + + xmlHttp.send(params); + } + + +
    +
    +
    + + +
    +
    +
    + +
    + +
    +
    -
    - -
    - -
    +
    +
    + +
    +
    -
    - -
    - -
    +
    +
    + +
    +
    -
    - -
    - -
    +
    +
    + +
    +
    -
    - -
    - -
    +
    +
    + +
    +
    -
    - -
    - -
    +
    +
    + +
    +
    -
    - -
    - -
    +
    +
    + +
    +
    -
    - -
    - -
    +
    +
    + +
    +
    -
    - -
    -
    -
    '; - ?> -
    +
    +
    + +
    +
    +
    '; + ?>
    -
    - -
    -
    -
    '; - ?> -
    +
    +
    + +
    +
    +
    '; + ?>
    - -
    -
    -
    -
    -
    - -
    -
        -
    '; - ?> -
    +
    + +
    +
    +
    +
    +
    + +
    +
        +
    '; + ?>
    -
    - -
    -
        -
    '; - ?> -
    +
    +
    + +
    +
        +
    '; + ?>
    -
    - -
    -
        -
    '; - ?> -
    +
    +
    + +
    +
        +
    '; + ?>
    -
    - -
    -
        -
    '; - ?> -
    +
    +
    + +
    +
        +
    '; + ?>
    -
    - -
    -
        -
    '; - ?> -
    +
    +
    + +
    +
        +
    '; + ?>
    - -
    -
    - -
    -
        -
    '; - ?> -
    +
    + +
    +
    + +
    +
        +
    '; + ?>
    -
    - -
    -
        -
    '; - ?> -
    +
    +
    + +
    +
        +
    '; + ?>
    -
    - -
    -
        -
    '; - ?> -
    +
    +
    + +
    +
        +
    '; + ?>
    -
    - -
    -
        -
    '; - ?> -
    +
    +
    + +
    +
        +
    '; + ?>
    - -
    -
    - -
    - -
    -
        -
        -
    - '; - - ?> -
    - -  
    - - :
    - - - -

    -

    +
    -
    +
    +
    -  
    +
    + +
    + -
    -  
    + echo ' +
        +
        +
    + '; - -
    -  
    + ?> +
    - -
        -
    '; - ?> +  
    -
    + :
    -
    -
    -
    -
    - -
        -
    '; ?> - -
    -  
    -
    -
    -
    -  
    +

    +

    -
    -
    -  
    +
    + +  
    + + +
    +  
    + + +
    +  
    + + +
        +
    '; + ?> + +
    -
    -
    -
    -
    - -
    - -
    - +
    +
    + +
    +
        +
    '; + ?> + +
    +  
    +
    + +
    +
    +  
    + +
    +
    +  
    +
    -
    - -
    - -
    +
    +
    +
    +
    + +
    + +
    +
    -
    - -
    -
    - -
    +
    +
    + +
    + +
    +
    +
    + +
    +
    +
    -
    -
    -
    - -
    - -
    +
    +
    +
    +
    + +
    + +
    + +
        +
    + -
        -
    +   () + + + '.$hesklang['e_attach'].''; + } + ?> +
    +
    +
    + +
    + /> +
    +
    +
    + $hesklang['B'] . ' (' . $hesklang['bytes'] . ')', + 'kB' => $hesklang['kB'] . ' (' . $hesklang['kilobytes'] . ')', + 'MB' => $hesklang['MB'] . ' (' . $hesklang['megabytes'] . ')', + 'GB' => $hesklang['GB'] . ' (' . $hesklang['gigabytes'] . ')', + ); + $tmp = hesk_formatBytes($hesk_settings['attachments']['max_size'], 0); + list($size, $unit) = explode(' ', $tmp); + ?> + +
    + /> +
    +
    + '.$hesklang['e_attach'].''; + if ($k == $unit) + { + echo ''; + } + else + { + echo ''; + } } + ?> + /> +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
        +
    '; + ?> +
    +
    +
    + +
    +
        +
    '; + ?> +
    +
    +
    + +
    +
        +
    '; + ?> +
    +
    +
    + +
    +
        +
    '; + ?> +
    +
    +
    + +
    +
        +
    '; + ?> +
    +
    +
    + +
    +
        +
    '; + ?> +
    +
    +
    + +
    +
        +
        +
    + '; ?>
    - +
    - /> +
    - $hesklang['B'] . ' (' . $hesklang['bytes'] . ')', - 'kB' => $hesklang['kB'] . ' (' . $hesklang['kilobytes'] . ')', - 'MB' => $hesklang['MB'] . ' (' . $hesklang['megabytes'] . ')', - 'GB' => $hesklang['GB'] . ' (' . $hesklang['gigabytes'] . ')', - ); - $tmp = hesk_formatBytes($hesk_settings['attachments']['max_size'], 0); - list($size, $unit) = explode(' ', $tmp); - ?> - +
    - /> +
    -
    - +
    +
    + +
    +
    - -
    - /> + +
    +
    - -
    +
    + +
    + +
    +
    +

    +
    +
    +
    +
    + +
    +
    +

    +
    +
    +
    + +
    + +
    +
    +

    +
    +
    +
    +
    + +
    +
    +

    +
    +
    +
    + + +
    +
    + + + + + + + + + + + + + + + + + + + + + '; + } // End FOR + ?> +
    + +
    +

    +
    +
    + + + '.$hesklang['opt'].' +
    +
    + + + +
    +
    +
    + +
    + +
    +
        +
    '; + ?> + + + + + + + + + + -
    -
    -
    - -
    - -
    -
        -
    '; - ?> -
    -
    -
    - -
    -
        -
    '; - ?> -
    +
    +
    - -
    -
        -
    '; - ?> + +
    + />
    - -
    -
        -
    '; - ?> + +
    + />
    - -
    -
        -
    '; - ?> + +
    + />
    - +
        -
    '; - ?> +
        +
    '; + ?>
    - +
        -
        -
    - '; +
        +
    '; ?>
    - -
    - -
    -
    -
    - -
    - -
    -
    -
    - -
    - -
    -
    -
    - -
    - -
    -
    -
    - -
    - -
    -
    -

    -
    -
    -
    -
    - -
    -
    -

    + +
    + autocomplete="off" />
    - -
    - -
    -
    -

    + +
    + autocomplete="off" />
    -
    - -
    -
    -

    -
    +
    + +
    -
    - -
    -
    - - - - - - - - - - + + - -
    -
    -
    - -
    - -
    -
        -
    '; - ?> - - - - - - - - - - - -
    -
    -
    -
    - -
    - /> -
    -
    -
    - -
    - /> -
    -
    -
    - -
    - /> -
    -
    -
    - -
    -
        -
    '; - ?> -
    -
    -
    - -
    -
        -
    '; - ?> -
    - -
    - -
    - autocomplete="off" /> -
    -
    -
    - -
    - autocomplete="off" /> -
    -
    -
    -
    - -
    -
    - - - + xmlHttp.send(params); + } + //--> + + - - - - -
    -
    - + echo ' +
        +
    '; + ?> + + + + + + + + +
    +
    + +
    + /> +
    +
    +
    + +
    + /> +
    +
    - +
        -
    '; +
        +
    '; ?>
    - -
    -
    -
    - +
        -
    '; - ?> - - - - - - +
    +
    '; + ?>
    -
    -
    - -
    - /> -
    -
    -
    - -
    - /> -
    -
    -
    - -
    -
        -
    '; - ?> -
    -
    -
    - -
    -
    -
    '; - ?> -
    - -
    - -
    - autocomplete="off" /> -
    +
    + +
    + autocomplete="off" />
    -
    - -
    - autocomplete="off" /> -
    +
    +
    + +
    + autocomplete="off" />
    -
    -
    - -
    +
    +
    +
    +
    -
    - - - - - - - - -
     
    +
    + + + + + + + + + +
     
    - - + + - - - -
    - -
    -
    - -
    - -
    - -
    -
    -
    - -
    - -
    -
    -

    -
    -
    - -
    -
    - -
    - -
    - + + - echo ' -
        -
    '; - ?> -
    -
    -
    -
    - -
    - -
    -
    - - - - - -
    -
    -
    -
    - -
    - -
    -
    - -
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    - -
    -
    - -
    -
    -
    -
    +
    - -
    -
    +
    - +
    - -
    -

    '.$server_time.'' ; ?>

    - + +
    +
    -
    -
    - -
    -
    -

    -
    + +
    +
    -
    -
    - -
    -
    -

    -
    +
    +

    + +
    +
    +
    - +
        -
    '; +
        +
    '; ?>
    -
    - -
    - +
    +
    + +
    + +
    + + + + + +
    -
    - +
    - +
    - -
    + +
    - +
    - +
    - -
    + +
    - -
    + +
    -
    - +
    +
    + +
    +
    + +
    - +
    - +
    +
    + + +
    +
    +
    + +
    + +
    +

    '.$server_time.'' ; ?>

    + +
    +
    +
    +
    +
    + +
    +
    +

    +
    +
    +
    +
    + +
    +
    +

    +
    +
    +
    +
    + +
    +
        +
    '; + ?> +
    +
    +
    + +
    + +
    +
    + +
    +
    + +
    + +
    +
    + +
    +
    +
    +
    + +
    +
    + +
    +
    +
    +
    + +
    +
    + +
    +
    +
    + +
    +
    +
    + +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    + + + + + + + + + + + + + fetch_assoc()) + { + $checkedEcho = ($row['IsClosed'] == 1) ? 'checked="checked"' : ''; + $isDisabled = false; + if ($row['IsNewTicketStatus'] || $row['IsClosedByClient'] || $row['IsCustomerReplyStatus'] || + $row['IsStaffClosedOption'] || $row['IsStaffReopenedStatus'] || $row['IsDefaultStaffReplyStatus'] + || $row['LockedTicketStatus']) + { + $isDisabled = true; + } + + echo ''; + echo ''; //Name + echo ''; // Short Name Language File + echo ''; // Long Name Language File + echo ''; // Text Color + echo ''; // Resolved Status? + echo ''; //Delete status? + echo ''; + } + + //Print out an additional blank space for adding a status + echo ''; + echo ''; + echo ''; // Short Name Language File + echo ''; // Long Name Language File + echo ''; // Text Color + echo ''; // Resolved Status? + echo ''; //Empty placeholder where the delete row is. + echo ''; + ?> + +
    '.$hesklang[$row['ShortNameContentKey']].''; + if ($isDisabled) + { + echo ''; + } else + { + echo ''; + } + echo '
    '.$hesklang['addNew'].'
    -
    -
    -
    - -
    - - - - - - - - - - - - +
    +
    +
    + +
    +
    '; - echo ''; //Name - echo ''; // Short Name Language File - echo ''; // Long Name Language File - echo ''; // Text Color - echo ''; // Resolved Status? - echo ''; //Delete status? - echo ''; + $selectedEcho = ($row['IsNewTicketStatus'] == 1) ? 'selected="selected"' : ''; + echo ''; } - - //Print out an additional blank space for adding a status - echo ''; - echo ''; - echo ''; // Short Name Language File - echo ''; // Long Name Language File - echo ''; // Text Color - echo ''; // Resolved Status? - echo ''; //Empty placeholder where the delete row is. - echo ''; ?> - -
    '.$hesklang[$row['ShortNameContentKey']].''; - if ($isDisabled) - { - echo ''; - } else - { - echo ''; - } - echo '
    '.$hesklang['addNew'].'
    -
    -
    -
    -
    - -
    - -
    +
    -
    - -
    - -
    +
    +
    + +
    +
    -
    - -
    - -
    +
    +
    + +
    +
    -
    - -
    - -
    +
    +
    + +
    +
    -
    - -
    - -
    +
    +
    + +
    +
    -
    - -
    - -
    +
    +
    + +
    +
    -
    - -
    - -
    +
    +
    + +
    +
    -
    -
    -
    - - '; - } - else - { - echo '
    '.$hesklang['e_save_settings'].''; - } - ?> -
    +
    +
    +
    +
    + + '; + } + else + { + echo '
    '.$hesklang['e_save_settings'].''; + } + ?>
    - -
    +
    + +
    Date: Sat, 9 Aug 2014 20:30:20 -0400 Subject: [PATCH 023/208] Removed the excess margin on the PM page --- admin/mail.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/admin/mail.php b/admin/mail.php index 1630580f..2591647a 100644 --- a/admin/mail.php +++ b/admin/mail.php @@ -133,9 +133,8 @@ function confirm_delete() //--> -
    -
    -
    +
    +
      From 27ba6ebc78fa783785daadac307a148505f0c634 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sat, 9 Aug 2014 22:09:11 -0400 Subject: [PATCH 024/208] The admin_ticket screen is now fully responsive. Woohoo! --- admin/admin_ticket.php | 313 +++++++++++++++++++++-------------------- css/hesk_newStyle.php | 19 +++ 2 files changed, 177 insertions(+), 155 deletions(-) diff --git a/admin/admin_ticket.php b/admin/admin_ticket.php index 1bf456ff..5aac7c08 100644 --- a/admin/admin_ticket.php +++ b/admin/admin_ticket.php @@ -515,11 +515,10 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php'); ?>
      - - - - - - - - - - - - - + +
      + + + + + + + +
      + - - - - - + + - - '', - 1 => '', - 2 => '', - 3 => '' - ); - - echo ''; + echo '


      '; - echo ''; - echo ''; - echo ''; + } + echo ' + + + + '; + } + echo ''; + echo '

      '.$hesklang['category'].'

      +

      '.$category['name'].'

      '; + + if ($can_change_cat) + { + echo ' + +
      +
      + + + + + + + + + '; } + + echo '
      '; ?> - - -
      -

      +
      +
      +
      +

      -

           - + +
      +
      +

      +
      +
      +

      +
      +
      + '.$hesklang['open_action'].''; } ?> -
      - : - -   - + + +
      +
      + : + +   + - -
      + ?> +
      ';} - elseif ($ticket['priority'] == 1) {echo 'class="highPriority">';} - else {echo 'class="medLowPriority">';} + ?> +
      + '.$hesklang['priority'].'

      '; + $options = array( + 0 => '', + 1 => '', + 2 => '', + 3 => '' + ); + + echo '
      ';} + elseif ($ticket['priority'] == 1) {echo 'highPriority">';} + else {echo 'medLowPriority">';} + + echo '

      '.$hesklang['priority'].'

      '; + + if ($ticket['priority']==0) {echo '

      '.$hesklang['critical'].'

      ';} + elseif ($ticket['priority']==1) {echo '

      '.$hesklang['high'].'

      ';} + elseif ($ticket['priority']==2) {echo '

      '.$hesklang['medium'].'

      ';} + else {echo '

      '.$hesklang['low'].'

      ';} + echo '
      +
      + + + + + + + + +
      + +
      '; + + echo '

      '.$hesklang['status'].'

      '; + $status_options = array(); + $results = hesk_dbQuery("SELECT `ID`, `ShortNameContentKey` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."statuses`"); + while ($row = $results->fetch_assoc()) + { + $status_options[$row['ID']] = ''; + } - if ($ticket['priority']==0) {echo '

      '.$hesklang['critical'].'

      ';} - elseif ($ticket['priority']==1) {echo '

      '.$hesklang['high'].'

      ';} - elseif ($ticket['priority']==2) {echo '

      '.$hesklang['medium'].'

      ';} - else {echo '

      '.$hesklang['low'].'

      ';} - echo '
      -
      + $ticketStatus = hesk_dbFetchAssoc(hesk_dbQuery("SELECT `TicketViewContentKey` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."statuses` WHERE ID = " .$ticket['status'])); + echo '

      '.$hesklang[$ticketStatus['TicketViewContentKey']].'

      '; + echo '
      - - + + ' . implode('', $status_options) . ' - + - + +
      +
      '; + echo '

      '.$hesklang['owner'].'

      +

      '; + + echo isset($admins[$ticket['owner']]) ? $admins[$ticket['owner']] : + ($can_assign_self ? $hesklang['unas'].' ['.$hesklang['asss'].']' : $hesklang['unas']); - - -

      '.$hesklang['status'].'

      '; - $status_options = array(); - $results = hesk_dbQuery("SELECT `ID`, `ShortNameContentKey` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."statuses`"); - while ($row = $results->fetch_assoc()) + if (hesk_checkPermission('can_assign_others',0)) + { + echo' +
      + + - - ' . implode('', $status_options) . ' - - - - - -
      -

      '.$hesklang['owner'].'

      -

      '; - - echo isset($admins[$ticket['owner']]) ? $admins[$ticket['owner']] : - ($can_assign_self ? $hesklang['unas'].' ['.$hesklang['asss'].']' : $hesklang['unas']); - - echo '


      '; - - if (hesk_checkPermission('can_assign_others',0)) + foreach ($admins as $k=>$v) + { + if ($k != $ticket['owner']) { - echo' -
      - - - - - - '; + echo ''; } - echo '

      '.$hesklang['category'].'

      -

      '.$category['name'].'

      '; - - if ($can_change_cat) - { - echo ' - -
      -
      - - - - - - - - -
      '; } - - echo '
      +
    +
    +
    Date: Sat, 9 Aug 2014 23:49:10 -0400 Subject: [PATCH 025/208] #23 Now "change language to" no longer appears when multilang is off --- index.php | 2 ++ ticket.php | 2 ++ 2 files changed, 4 insertions(+) diff --git a/index.php b/index.php index 31ae6143..7e559085 100644 --- a/index.php +++ b/index.php @@ -106,6 +106,7 @@ function print_add_ticket()
    +
    @@ -114,6 +115,7 @@ function print_add_ticket()
    +

    diff --git a/ticket.php b/ticket.php index 314a10d1..6b5a7aeb 100644 --- a/ticket.php +++ b/ticket.php @@ -212,6 +212,7 @@ require_once(HESK_PATH . 'inc/header.inc.php');
    +
    @@ -220,6 +221,7 @@ require_once(HESK_PATH . 'inc/header.inc.php');
    +

    From de7ed0f1f3f72eeb9e7048ed9399a64cb76035ec Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Wed, 3 Sep 2014 21:32:04 -0400 Subject: [PATCH 026/208] Half-baked newish admin dashboard --- admin/admin_main.php | 12 ++++----- inc/ticket_list.inc.php | 60 +++++++++++++---------------------------- language/en/text.php | 2 +- 3 files changed, 24 insertions(+), 50 deletions(-) diff --git a/admin/admin_main.php b/admin/admin_main.php index f2cae84a..0860a0bf 100644 --- a/admin/admin_main.php +++ b/admin/admin_main.php @@ -59,7 +59,7 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php'); ?>
    -
    +
    -
     
    -

    '.$hesklang['open_tickets'].'

    -
     
    -
    - '; +
    +
    +

    '.$hesklang['open_tickets'].' '.$hesklang['nti'].'

    +
    '; // The rest of the panel will be printed by print_tickets.inc.php } /* Reset default settings? */ diff --git a/inc/ticket_list.inc.php b/inc/ticket_list.inc.php index 38cda5b4..33bdc779 100644 --- a/inc/ticket_list.inc.php +++ b/inc/ticket_list.inc.php @@ -115,33 +115,29 @@ if ($total > 0) if ($pages > 1) { + //-- Precondition: The panel has already been created, and there is NO open
    tag yet. echo ' -
    -
    - '.sprintf($hesklang['tickets_on_pages'],$total,$pages).' '.$hesklang['jump_page'].'
    '; - +
    + '.sprintf($hesklang['tickets_on_pages'],$total,$pages).' '.$hesklang['jump_page'].'
    '; + /* List pages */ + echo '
      '; if ($pages > 7) { if ($page > 2) { - echo '«   '; + echo '
    • «
    • '; // << } if ($prev_page) { - echo '   '; + echo '
    • '; // < } } @@ -151,11 +147,11 @@ if ($total > 0) { if ($i == $page) { - echo ' '.$i.' '; + echo '
    • '.$i.'
    • '; } else { - echo ' '.$i.' '; + echo '
    • '.$i.'
    • '; } } } @@ -164,36 +160,16 @@ if ($total > 0) { if ($next_page) { - echo '   '; + echo '
    • '; // > } if ($page < ($pages - 1)) { - echo '   »'; + echo '
    • »
    • '; // >> } } + echo '
    '; - echo '

    '; - echo ' - '; - - } // end PAGES > 1 - else - { - echo ' -
    -
    - '.sprintf($hesklang['tickets_on_pages'],$total,$pages).' -
    - -
    '; } /* We have the full SQL query now, get tickets */ diff --git a/language/en/text.php b/language/en/text.php index 7988b9e0..58a37197 100644 --- a/language/en/text.php +++ b/language/en/text.php @@ -410,7 +410,7 @@ $hesklang['remember_user']='Remember my username'; $hesklang['wrong_user']='Wrong username'; $hesklang['no_permission']='You don\'t have permission to perform this task, please login with an account that has.'; $hesklang['tickets_on_pages']='Number of tickets: %d | Number of pages: %d'; // First %d is replaced with number of tickets, second %d with number of pages -$hesklang['jump_page']=' | Jump to page:'; +$hesklang['jump_page']='Jump to page:'; $hesklang['no_tickets_open']='No unresolved tickets found'; $hesklang['no_tickets_crit']='No tickets found matching your criteria'; $hesklang['confirm_execute']='Are you sure you want to continue?'; From 835ad2acf70b5557ffc6547ea9ba96a27428c115 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Wed, 3 Sep 2014 22:07:30 -0400 Subject: [PATCH 027/208] Still a half-baked implementation. Jump to page is driving me nuts. --- inc/ticket_list.inc.php | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/inc/ticket_list.inc.php b/inc/ticket_list.inc.php index 33bdc779..93d20934 100644 --- a/inc/ticket_list.inc.php +++ b/inc/ticket_list.inc.php @@ -118,16 +118,12 @@ if ($total > 0) //-- Precondition: The panel has already been created, and there is NO open
    tag yet. echo '
    - '.sprintf($hesklang['tickets_on_pages'],$total,$pages).' '.$hesklang['jump_page'].'
    '; + '.sprintf($hesklang['tickets_on_pages'],$total,$pages).'
    '; /* List pages */ - echo '
      '; + echo '
      +
      +
        '; if ($pages > 7) { if ($page > 2) @@ -168,7 +164,18 @@ if ($total > 0) echo '
      • »
      • '; // >> } } - echo '
      '; + echo '
    +
    +
    '.$hesklang['jump_page'].' + +
    +
    '; } From 8cd7aebaae864cb37f2e220c8b85ed4a655138f2 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sat, 6 Sep 2014 22:19:59 -0400 Subject: [PATCH 028/208] #24 the search tickets screen has been restyled --- admin/admin_main.php | 2 +- admin/show_tickets.php | 7 +- inc/show_search_form.inc.php | 434 ++++++++++++++++++----------------- inc/ticket_list.inc.php | 61 ++--- 4 files changed, 247 insertions(+), 257 deletions(-) diff --git a/admin/admin_main.php b/admin/admin_main.php index 0860a0bf..613b4f7f 100644 --- a/admin/admin_main.php +++ b/admin/admin_main.php @@ -72,7 +72,7 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php'); echo '
    -

    '.$hesklang['open_tickets'].' '.$hesklang['nti'].'

    +

    '.$hesklang['open_tickets'].' '.$hesklang['nti'].'

    '; // The rest of the panel will be printed by print_tickets.inc.php } diff --git a/admin/show_tickets.php b/admin/show_tickets.php index 42aa8926..3d29d860 100644 --- a/admin/show_tickets.php +++ b/admin/show_tickets.php @@ -58,12 +58,15 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php'); ?> -
    +
    -

    +
    + - - - - + +
    -
    -

    -
    - - - - + + + + + + + + + + + + + + + + + + + + +
    :   - - - - fetch_assoc()) - { - if ($rowCounter > 3) +
    +
    +

    +
    +
    +
    + + + + + + + + + +
    + + + + + + +
    :   + + + fetch_assoc()) + { + if ($rowCounter > 3) + { + echo ''; + $rowCounter = 1; + } + echo ''; + + $rowCounter++; + } + ?> + +
    '.$hesklang[$row['ShortNameContentKey']].'
    +
    + +
    +  
    + + +
     
    +
    + +
    + + + + + + + + + + + + + + + + + + + + - -
    :   + + + + + + + + + + + + +
     
     
    + +
    :   + + + + '; - $rowCounter = 1; + ?> +
    + + + + + + +
    + +
    + + +
    + +
     
    + +
    :   + + + + + + + + + + + +
     
    + +
    :   + + + + '; - - $rowCounter++; - } - ?> - -
    + + '.$hesklang[$row['ShortNameContentKey']].'
    - -
    - -

    - - -
     
    -
    - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    :   - - - - - - - - - - - - -
     
     
    - -
    :   - - - - - - - -
    - - -
    - - -
    - - -
    - -
     
    - -
    :   - - - - - - - - - - - -
     
    - -
    :   - - - - - - - - - - - -
    - - - 
     
    - -
    :   -
    -
    :  
    :   - -| -
    :   - -
    - () - -
    - -

    -

    - + else + { + echo ' '; + } + ?> +
     
     
    + +
    :   +
    +
    :  
    :   + + | +
    :   + +
    + () + +
    + +

    +

    + + + +
    + +
    +
    - - -
    -
    - +
    +
    +

    +
    +
    + + @@ -336,28 +337,6 @@ EOC;
    -

    -
    - +
    - -
    +
    />
    +
    +
    - - + - - + - - + - - + +
    :   +:  
    :   +:  
    />
    :   +:  
    :  
    :  
    @@ -423,6 +427,8 @@ if ($can_view_unassigned)
    + + diff --git a/inc/ticket_list.inc.php b/inc/ticket_list.inc.php index 93d20934..7c83845d 100644 --- a/inc/ticket_list.inc.php +++ b/inc/ticket_list.inc.php @@ -61,6 +61,8 @@ $mysql_time = hesk_dbTime(); $result = hesk_dbQuery($sql_count); $total = hesk_dbResult($result); +//-- Precondition: The panel has already been created, and there is NO open
    tag yet. +echo '
    '; if ($total > 0) { @@ -112,13 +114,11 @@ if ($total > 0) $prev_page = ($page - 1 <= 0) ? 0 : $page - 1; $next_page = ($page + 1 > $pages) ? 0 : $page + 1; + + echo sprintf($hesklang['tickets_on_pages'],$total,$pages).'
    '; - if ($pages > 1) + if ($pages > 1) { - //-- Precondition: The panel has already been created, and there is NO open
    tag yet. - echo ' -
    - '.sprintf($hesklang['tickets_on_pages'],$total,$pages).'
    '; /* List pages */ echo '
    @@ -166,16 +166,18 @@ if ($total > 0) } echo '
    -
    '.$hesklang['jump_page'].' - '; for ($i=1;$i<=$pages;$i++) { $tmp = ($page == $i) ? ' selected="selected"' : ''; echo ''; } - echo' + echo'
    -
    '; +
    +
    '; } @@ -240,7 +242,6 @@ if ($total > 0) } $i = 0; - $checkall = ''; $group_tmp = ''; $is_table = 0; @@ -260,7 +261,7 @@ if ($total > 0) $first_line = '(' . $hesklang['unas'] . ')'." \n\n"; if ($ticket['owner'] == $_SESSION['id']) { - $owner = ' '; + $owner = ' '; $first_line = $hesklang['tasy2'] . " \n\n"; } elseif ($ticket['owner']) @@ -269,14 +270,14 @@ if ($total > 0) { $admins[$ticket['owner']] = $hesklang['e_udel']; } - $owner = ' '; + $owner = ' '; $first_line = $hesklang['taso3'] . ' ' . $admins[$ticket['owner']] . " \n\n"; } $tagged = ''; if ($ticket['archive']) { - $tagged = ' '; + $tagged = ' '; } $statusName = hesk_dbFetchAssoc(hesk_dbQuery("SELECT `ShortNameContentKey`, `TextColor` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."statuses` WHERE ID = ".$ticket['status'])); @@ -293,7 +294,7 @@ if ($total > 0) $color = 'warning'; break; case 2: - $ticket['priority']=''; + $ticket['priority']=''; break; default: $ticket['priority']=''; @@ -315,8 +316,8 @@ if ($total > 0) $ticket['message'] = $first_line . substr(strip_tags($ticket['message']),0,200).'...'; echo << -
     
      $ticket[trackid] $ticket[lastchange] $ticket[name]
    -
    - -    - - -    - - - - -   -
    +
    +
    0 @@ -421,10 +402,10 @@ function hesk_print_list_head() global $href, $query, $sort_possible, $hesklang; ?>
    - +
    - + From 8398efa538775c62e43f7eb6f1d2821f7a9cc052 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 7 Sep 2014 01:50:56 -0400 Subject: [PATCH 029/208] #25 Dashboard columns can now be added/removed via JavaScript! --- .gitignore | 1 - admin/find_tickets.php | 10 +- inc/prepare_ticket_search.inc.php | 177 ++++++++++++++++++++++++++++++ inc/ticket_list.inc.php | 149 ++++++++++++++++++++++--- js/nuMods-javascript.js | 19 ++++ language/en/text.php | 4 + 6 files changed, 339 insertions(+), 21 deletions(-) create mode 100644 inc/prepare_ticket_search.inc.php diff --git a/.gitignore b/.gitignore index cb56f7f4..3c8db864 100644 --- a/.gitignore +++ b/.gitignore @@ -186,7 +186,6 @@ inc/mail/smtp.php inc/pipe_functions.inc.php inc/posting_functions.inc.php inc/prepare_ticket_export.inc.php -inc/prepare_ticket_search.inc.php inc/print_group.inc.php inc/recaptcha/LICENSE inc/recaptcha/index.htm diff --git a/admin/find_tickets.php b/admin/find_tickets.php index 4e35e3a7..24974da9 100644 --- a/admin/find_tickets.php +++ b/admin/find_tickets.php @@ -65,8 +65,12 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php'); '; + } + } + echo << - - - - - - - + + + + + + + + + $customFieldsHtml EOC; @@ -334,9 +349,98 @@ EOC;  
    - +
    - -

    +
    +
    +
    +
    +

    +
    -
    - 0) ? $tmp : $hesk_settings['max_listings']; + +$tmp = intval( hesk_GET('page', 1) ); +$page = ($tmp > 1) ? $tmp : 1; + +/* Acceptable $sort values and default asc(1)/desc(0) setting */ +$sort_possible = array( +'trackid' => 1, +'lastchange' => 0, +'name' => 1, +'subject' => 1, +'status' => 1, +'lastreplier' => 1, +'priority' => 1, +'category' => 1, +'dt' => 0, +'id' => 1, +'owner' => 1, +'custom1' => 1, +'custom2' => 1, +'custom3' => 1, +'custom4' => 1, +'custom5' => 1, +'custom6' => 1, +'custom7' => 1, +'custom8' => 1, +'custom9' => 1, +'custom10' => 1, +'custom11' => 1, +'custom12' => 1, +'custom13' => 1, +'custom14' => 1, +'custom15' => 1, +'custom16' => 1, +'custom17' => 1, +'custom18' => 1, +'custom19' => 1, +'custom20' => 1 +); + +/* These values should have collate appended in SQL */ +$sort_collation = array( +'name', +'subject', +); + +/* Acceptable $group values and default asc(1)/desc(0) setting */ +$group_possible = array( +'owner' => 1, +'priority' => 1, +'category' => 1, +); + +/* Start the order by part of the SQL query */ +$sql .= " ORDER BY "; + +/* Group tickets? Default: no */ +if (isset($_GET['g']) && ! is_array($_GET['g']) && isset($group_possible[$_GET['g']])) +{ + $group = hesk_input($_GET['g']); + + if ($group == 'priority' && isset($_GET['sort']) && ! is_array($_GET['sort']) && $_GET['sort'] == 'priority') + { + // No need to group by priority if we are already sorting by priority + } + elseif ($group == 'owner') + { + // If group by owner place own tickets on top + $sql .= " CASE WHEN `owner` = '".intval($_SESSION['id'])."' THEN 1 ELSE 0 END DESC, `owner` ASC, "; + } + else + { + $sql .= ' `'.hesk_dbEscape($group).'` '; + $sql .= $group_possible[$group] ? 'ASC, ' : 'DESC, '; + } +} +else +{ + $group = ''; +} + + +/* Show critical tickets always on top? Default: yes */ +$cot = (isset($_GET['cot']) && intval($_GET['cot']) == 1) ? 1 : 0; +if (!$cot) +{ + $sql .= " CASE WHEN `priority` = '0' THEN 1 ELSE 0 END DESC , "; +} + +/* Sort by which field? */ +if (isset($_GET['sort']) && ! is_array($_GET['sort']) && isset($sort_possible[$_GET['sort']])) +{ + $sort = hesk_input($_GET['sort']); + + $sql .= $sort == 'lastreplier' ? " CASE WHEN `lastreplier` = '0' THEN 0 ELSE 1 END DESC, COALESCE(`replierid`, NULLIF(`lastreplier`, '0'), `name`) " : ' `'.hesk_dbEscape($sort).'` '; + + // Need to set MySQL collation? + if ( in_array($_GET['sort'], $sort_collation) ) + { + $sql .= " COLLATE '" . hesk_dbEscape($hesklang['_COLLATE']) . "' "; + } +} +else +{ + /* Default sorting by ticket status */ + $sql .= ' `status` '; + $sort = 'status'; +} + +/* Ascending or Descending? */ +if (isset($_GET['asc']) && intval($_GET['asc'])==0) +{ + $sql .= ' DESC '; + $asc = 0; + $asc_rev = 1; + + $sort_possible[$sort] = 1; +} +else +{ + $sql .= ' ASC '; + $asc = 1; + $asc_rev = 0; + if (!isset($_GET['asc'])) + { + $is_default = 1; + } + + $sort_possible[$sort] = 0; +} + +/* In the end same results should always be sorted by priority */ +if ($sort != 'priority') +{ + $sql .= ' , `priority` ASC '; +} + +# Uncomment for debugging purposes +# echo "SQL: $sql
    "; diff --git a/inc/ticket_list.inc.php b/inc/ticket_list.inc.php index 7c83845d..33e2033a 100644 --- a/inc/ticket_list.inc.php +++ b/inc/ticket_list.inc.php @@ -314,17 +314,32 @@ if ($total > 0) $ticket['archive'] = !($ticket['archive']) ? $hesklang['no'] : $hesklang['yes']; $ticket['message'] = $first_line . substr(strip_tags($ticket['message']),0,200).'...'; + $ownerColumn = $ticket['owner'] != 0 ? $admins[$ticket['owner']] : '('.$hesklang['unas'].')'; + + $customFieldsHtml = ''; + for ($i = 0; $i <= 20; $i++) { + if ($hesk_settings['custom_fields']['custom'.$i]['use']) { + $display = 'display: none'; + if ((isset($_GET['sort']) && $_GET['sort'] == 'custom'.$i) || (isset($_GET['what']) && $_GET['what'] == 'custom'.$i)) { + $display = ''; + } + $customFieldsHtml .= '
    '.$ticket['custom'.$i].' $ticket[trackid]$ticket[lastchange]$ticket[name]$tagged$owner$ticket[subject]$ticket[status] $ticket[repliername]$ticket[priority] $ticket[trackid]$ticket[lastchange]$ticket[name]$tagged$owner$ticket[subject]$ticket[status] $ticket[repliername]$ticket[priority]
    + - '; - echo ''; - echo ''; - echo ''; + echo ''; + echo ''; + echo ''; echo ''; } @@ -2200,29 +2200,29 @@ if ( defined('HESK_DEMO') )
    +
    + + +
    - - - - - - - + + + + + + + + + + '.$hesk_settings['custom_fields']['custom'.$i]['name'].''; + } + } + ?> Date: Sat, 6 Sep 2014 23:52:16 -0600 Subject: [PATCH 030/208] add waffle.io badge --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 8c06c1f4..b8506378 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ +[![Stories in Ready](https://badge.waffle.io/mkoch227/numods.png?label=ready&title=Ready)](https://waffle.io/mkoch227/numods)

    NuMods v1.2.4

    This branch contains all files modified from the base version of HESK to become NuMods, a set of modifications for HESK v2.x From 820276c402da847c67fdb600c23d538211a32ee6 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 7 Sep 2014 11:43:37 -0400 Subject: [PATCH 031/208] #46 The new ticket page uses a panel instead of a tabbed bar --- admin/new_ticket.php | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/admin/new_ticket.php b/admin/new_ticket.php index 17125e09..8fdc44eb 100644 --- a/admin/new_ticket.php +++ b/admin/new_ticket.php @@ -91,24 +91,18 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
  • - -
    -
    -
    -
    - -
    -
    -

    -
    -

    *

    -
    -
    -
    +
    +
    +
    +
    +
    +

    +
    +

    *

    +
    +
    -
    +
    Date: Sun, 7 Sep 2014 21:42:47 -0400 Subject: [PATCH 032/208] #26 EXPERIMENTAL support for right-to-left text direction --- admin/admin_main.php | 2 +- admin/admin_settings.php | 20 +- admin/admin_ticket.php | 6 +- admin/edit_post.php | 5 - admin/mail.php | 2 +- admin/manage_users.php | 2 +- attachments/__latest.txt | 1 + css/bootstrap-rtl.min.css | 9 + css/hesk_newStyle.php | 8 + css/hesk_newStyleRTL.php | 346 +++++++++++++ hesk_style_v25RTL.css | 745 ++++++++++++++++++++++++++++ inc/header.inc.php | 12 +- inc/headerAdmin.inc.php | 12 +- inc/knowledgebase_functions.inc.php | 18 +- inc/show_search_form.inc.php | 6 +- inc/ticket_list.inc.php | 6 +- knowledgebase.php | 16 +- nuMods_settings.inc.php | 3 + print.php | 3 +- ticket.php | 4 +- 20 files changed, 1177 insertions(+), 49 deletions(-) create mode 100644 attachments/__latest.txt create mode 100644 css/bootstrap-rtl.min.css create mode 100644 css/hesk_newStyleRTL.php create mode 100644 hesk_style_v25RTL.css diff --git a/admin/admin_main.php b/admin/admin_main.php index 613b4f7f..4b72cc43 100644 --- a/admin/admin_main.php +++ b/admin/admin_main.php @@ -72,7 +72,7 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php'); echo '
    -

    '.$hesklang['open_tickets'].' '.$hesklang['nti'].'

    +

    '.$hesklang['open_tickets'].' '.$hesklang['nti'].'

    '; // The rest of the panel will be printed by print_tickets.inc.php } diff --git a/admin/admin_settings.php b/admin/admin_settings.php index 1f37ca6d..8997291e 100644 --- a/admin/admin_settings.php +++ b/admin/admin_settings.php @@ -103,7 +103,7 @@ if ( defined('HESK_DEMO') )
    - - - - -
    +
    : @@ -141,20 +141,20 @@ if ( defined('HESK_DEMO') ) ?>
    + :
    +
    :
    + /hesk_settings.inc.php @@ -169,7 +169,7 @@ if ( defined('HESK_DEMO') )
    + / @@ -1515,11 +1515,11 @@ if ( defined('HESK_DEMO') ) - + - +
      
    @@ -1632,7 +1632,7 @@ if ( defined('HESK_DEMO') ) - +
    @@ -2052,7 +2052,7 @@ function hesk_cacheLatestVersion($latest) function hesk_testLanguage($return_options = 0) { - global $hesk_settings, $hesklang; + global $hesk_settings, $hesklang, $nuMods_settings; /* Get a list of valid emails */ include_once(HESK_PATH . 'inc/email_functions.inc.php'); @@ -2209,7 +2209,7 @@ function hesk_testLanguage($return_options = 0) background:#fff; color: black; font : 68.8%/1.5 Verdana, Geneva, Arial, Helvetica, sans-serif; - text-align:left; + text-align: ; } p diff --git a/admin/admin_ticket.php b/admin/admin_ticket.php index 5aac7c08..622d7814 100644 --- a/admin/admin_ticket.php +++ b/admin/admin_ticket.php @@ -973,7 +973,7 @@ function hesk_getAdminButtonsInTicket($reply=0,$white=1) { global $hesk_settings, $hesklang, $ticket, $reply, $trackingID, $can_edit, $can_archive, $can_delete; - $options = '
    '; + $options = '
    '; /* Style and mousover/mousout */ $tmp = $white ? 'White' : 'Blue'; @@ -1156,7 +1156,7 @@ function hesk_printReplyForm() { ?> -

    +

    @@ -1182,7 +1182,7 @@ function hesk_printReplyForm() {
    -
    +
    diff --git a/admin/edit_post.php b/admin/edit_post.php index 49d959dd..2a7295a5 100644 --- a/admin/edit_post.php +++ b/admin/edit_post.php @@ -407,11 +407,6 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
    - -

    - -

     

    -
    +
    -
    +
    diff --git a/attachments/__latest.txt b/attachments/__latest.txt new file mode 100644 index 00000000..ec318b1a --- /dev/null +++ b/attachments/__latest.txt @@ -0,0 +1 @@ +1410138724|2.5.5 \ No newline at end of file diff --git a/css/bootstrap-rtl.min.css b/css/bootstrap-rtl.min.css new file mode 100644 index 00000000..734b03aa --- /dev/null +++ b/css/bootstrap-rtl.min.css @@ -0,0 +1,9 @@ +/******************************************************************************* + * bootstrap-rtl (Version 3.2.0-rc5) + * Author: Morteza Ansarinia (http://github.com/morteza) + * Created on: August 29,2014 + * Project: bootstrap-rtl + * Copyright: See the file "LICENSE.md" for the full license governing this code. + *******************************************************************************/ + +html{direction:rtl}body{direction:rtl}.list-unstyled{padding-right:0;padding-left:none}.list-inline{padding-right:0;padding-left:none;margin-right:-5px;margin-left:0}dd{margin-right:0;margin-left:none}@media (min-width:768px){.dl-horizontal dt{float:right;clear:right;text-align:left}.dl-horizontal dd{margin-right:180px;margin-left:0}}blockquote{border-right:5px solid #eee;border-left:0}.blockquote-reverse,blockquote.pull-left{padding-left:15px;padding-right:0;border-left:5px solid #eee;border-right:0;text-align:left}.col-xs-1,.col-sm-1,.col-md-1,.col-lg-1,.col-xs-2,.col-sm-2,.col-md-2,.col-lg-2,.col-xs-3,.col-sm-3,.col-md-3,.col-lg-3,.col-xs-4,.col-sm-4,.col-md-4,.col-lg-4,.col-xs-5,.col-sm-5,.col-md-5,.col-lg-5,.col-xs-6,.col-sm-6,.col-md-6,.col-lg-6,.col-xs-7,.col-sm-7,.col-md-7,.col-lg-7,.col-xs-8,.col-sm-8,.col-md-8,.col-lg-8,.col-xs-9,.col-sm-9,.col-md-9,.col-lg-9,.col-xs-10,.col-sm-10,.col-md-10,.col-lg-10,.col-xs-11,.col-sm-11,.col-md-11,.col-lg-11,.col-xs-12,.col-sm-12,.col-md-12,.col-lg-12{position:relative;min-height:1px;padding-left:15px;padding-right:15px}.col-xs-1,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-10,.col-xs-11,.col-xs-12{float:right}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{left:100%;right:auto}.col-xs-pull-11{left:91.66666667%;right:auto}.col-xs-pull-10{left:83.33333333%;right:auto}.col-xs-pull-9{left:75%;right:auto}.col-xs-pull-8{left:66.66666667%;right:auto}.col-xs-pull-7{left:58.33333333%;right:auto}.col-xs-pull-6{left:50%;right:auto}.col-xs-pull-5{left:41.66666667%;right:auto}.col-xs-pull-4{left:33.33333333%;right:auto}.col-xs-pull-3{left:25%;right:auto}.col-xs-pull-2{left:16.66666667%;right:auto}.col-xs-pull-1{left:8.33333333%;right:auto}.col-xs-pull-0{left:auto;right:auto}.col-xs-push-12{right:100%;left:0}.col-xs-push-11{right:91.66666667%;left:0}.col-xs-push-10{right:83.33333333%;left:0}.col-xs-push-9{right:75%;left:0}.col-xs-push-8{right:66.66666667%;left:0}.col-xs-push-7{right:58.33333333%;left:0}.col-xs-push-6{right:50%;left:0}.col-xs-push-5{right:41.66666667%;left:0}.col-xs-push-4{right:33.33333333%;left:0}.col-xs-push-3{right:25%;left:0}.col-xs-push-2{right:16.66666667%;left:0}.col-xs-push-1{right:8.33333333%;left:0}.col-xs-push-0{right:auto;left:0}.col-xs-offset-12{margin-right:100%;margin-left:0}.col-xs-offset-11{margin-right:91.66666667%;margin-left:0}.col-xs-offset-10{margin-right:83.33333333%;margin-left:0}.col-xs-offset-9{margin-right:75%;margin-left:0}.col-xs-offset-8{margin-right:66.66666667%;margin-left:0}.col-xs-offset-7{margin-right:58.33333333%;margin-left:0}.col-xs-offset-6{margin-right:50%;margin-left:0}.col-xs-offset-5{margin-right:41.66666667%;margin-left:0}.col-xs-offset-4{margin-right:33.33333333%;margin-left:0}.col-xs-offset-3{margin-right:25%;margin-left:0}.col-xs-offset-2{margin-right:16.66666667%;margin-left:0}.col-xs-offset-1{margin-right:8.33333333%;margin-left:0}.col-xs-offset-0{margin-right:0;margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12{float:right}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{left:100%;right:auto}.col-sm-pull-11{left:91.66666667%;right:auto}.col-sm-pull-10{left:83.33333333%;right:auto}.col-sm-pull-9{left:75%;right:auto}.col-sm-pull-8{left:66.66666667%;right:auto}.col-sm-pull-7{left:58.33333333%;right:auto}.col-sm-pull-6{left:50%;right:auto}.col-sm-pull-5{left:41.66666667%;right:auto}.col-sm-pull-4{left:33.33333333%;right:auto}.col-sm-pull-3{left:25%;right:auto}.col-sm-pull-2{left:16.66666667%;right:auto}.col-sm-pull-1{left:8.33333333%;right:auto}.col-sm-pull-0{left:auto;right:auto}.col-sm-push-12{right:100%;left:0}.col-sm-push-11{right:91.66666667%;left:0}.col-sm-push-10{right:83.33333333%;left:0}.col-sm-push-9{right:75%;left:0}.col-sm-push-8{right:66.66666667%;left:0}.col-sm-push-7{right:58.33333333%;left:0}.col-sm-push-6{right:50%;left:0}.col-sm-push-5{right:41.66666667%;left:0}.col-sm-push-4{right:33.33333333%;left:0}.col-sm-push-3{right:25%;left:0}.col-sm-push-2{right:16.66666667%;left:0}.col-sm-push-1{right:8.33333333%;left:0}.col-sm-push-0{right:auto;left:0}.col-sm-offset-12{margin-right:100%;margin-left:0}.col-sm-offset-11{margin-right:91.66666667%;margin-left:0}.col-sm-offset-10{margin-right:83.33333333%;margin-left:0}.col-sm-offset-9{margin-right:75%;margin-left:0}.col-sm-offset-8{margin-right:66.66666667%;margin-left:0}.col-sm-offset-7{margin-right:58.33333333%;margin-left:0}.col-sm-offset-6{margin-right:50%;margin-left:0}.col-sm-offset-5{margin-right:41.66666667%;margin-left:0}.col-sm-offset-4{margin-right:33.33333333%;margin-left:0}.col-sm-offset-3{margin-right:25%;margin-left:0}.col-sm-offset-2{margin-right:16.66666667%;margin-left:0}.col-sm-offset-1{margin-right:8.33333333%;margin-left:0}.col-sm-offset-0{margin-right:0;margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12{float:right}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{left:100%;right:auto}.col-md-pull-11{left:91.66666667%;right:auto}.col-md-pull-10{left:83.33333333%;right:auto}.col-md-pull-9{left:75%;right:auto}.col-md-pull-8{left:66.66666667%;right:auto}.col-md-pull-7{left:58.33333333%;right:auto}.col-md-pull-6{left:50%;right:auto}.col-md-pull-5{left:41.66666667%;right:auto}.col-md-pull-4{left:33.33333333%;right:auto}.col-md-pull-3{left:25%;right:auto}.col-md-pull-2{left:16.66666667%;right:auto}.col-md-pull-1{left:8.33333333%;right:auto}.col-md-pull-0{left:auto;right:auto}.col-md-push-12{right:100%;left:0}.col-md-push-11{right:91.66666667%;left:0}.col-md-push-10{right:83.33333333%;left:0}.col-md-push-9{right:75%;left:0}.col-md-push-8{right:66.66666667%;left:0}.col-md-push-7{right:58.33333333%;left:0}.col-md-push-6{right:50%;left:0}.col-md-push-5{right:41.66666667%;left:0}.col-md-push-4{right:33.33333333%;left:0}.col-md-push-3{right:25%;left:0}.col-md-push-2{right:16.66666667%;left:0}.col-md-push-1{right:8.33333333%;left:0}.col-md-push-0{right:auto;left:0}.col-md-offset-12{margin-right:100%;margin-left:0}.col-md-offset-11{margin-right:91.66666667%;margin-left:0}.col-md-offset-10{margin-right:83.33333333%;margin-left:0}.col-md-offset-9{margin-right:75%;margin-left:0}.col-md-offset-8{margin-right:66.66666667%;margin-left:0}.col-md-offset-7{margin-right:58.33333333%;margin-left:0}.col-md-offset-6{margin-right:50%;margin-left:0}.col-md-offset-5{margin-right:41.66666667%;margin-left:0}.col-md-offset-4{margin-right:33.33333333%;margin-left:0}.col-md-offset-3{margin-right:25%;margin-left:0}.col-md-offset-2{margin-right:16.66666667%;margin-left:0}.col-md-offset-1{margin-right:8.33333333%;margin-left:0}.col-md-offset-0{margin-right:0;margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12{float:right}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{left:100%;right:auto}.col-lg-pull-11{left:91.66666667%;right:auto}.col-lg-pull-10{left:83.33333333%;right:auto}.col-lg-pull-9{left:75%;right:auto}.col-lg-pull-8{left:66.66666667%;right:auto}.col-lg-pull-7{left:58.33333333%;right:auto}.col-lg-pull-6{left:50%;right:auto}.col-lg-pull-5{left:41.66666667%;right:auto}.col-lg-pull-4{left:33.33333333%;right:auto}.col-lg-pull-3{left:25%;right:auto}.col-lg-pull-2{left:16.66666667%;right:auto}.col-lg-pull-1{left:8.33333333%;right:auto}.col-lg-pull-0{left:auto;right:auto}.col-lg-push-12{right:100%;left:0}.col-lg-push-11{right:91.66666667%;left:0}.col-lg-push-10{right:83.33333333%;left:0}.col-lg-push-9{right:75%;left:0}.col-lg-push-8{right:66.66666667%;left:0}.col-lg-push-7{right:58.33333333%;left:0}.col-lg-push-6{right:50%;left:0}.col-lg-push-5{right:41.66666667%;left:0}.col-lg-push-4{right:33.33333333%;left:0}.col-lg-push-3{right:25%;left:0}.col-lg-push-2{right:16.66666667%;left:0}.col-lg-push-1{right:8.33333333%;left:0}.col-lg-push-0{right:auto;left:0}.col-lg-offset-12{margin-right:100%;margin-left:0}.col-lg-offset-11{margin-right:91.66666667%;margin-left:0}.col-lg-offset-10{margin-right:83.33333333%;margin-left:0}.col-lg-offset-9{margin-right:75%;margin-left:0}.col-lg-offset-8{margin-right:66.66666667%;margin-left:0}.col-lg-offset-7{margin-right:58.33333333%;margin-left:0}.col-lg-offset-6{margin-right:50%;margin-left:0}.col-lg-offset-5{margin-right:41.66666667%;margin-left:0}.col-lg-offset-4{margin-right:33.33333333%;margin-left:0}.col-lg-offset-3{margin-right:25%;margin-left:0}.col-lg-offset-2{margin-right:16.66666667%;margin-left:0}.col-lg-offset-1{margin-right:8.33333333%;margin-left:0}.col-lg-offset-0{margin-right:0;margin-left:0}}th{text-align:right}@media screen and (max-width:767px){.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>thead>tr>th:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-right:0;border-left:auto}.table-responsive>.table-bordered>thead>tr>th:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-left:0;border-right:auto}}.radio label,.checkbox label{padding-right:20px;padding-left:auto}.radio input[type=radio],.radio-inline input[type=radio],.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox]{margin-right:-20px;margin-left:auto}.radio-inline,.checkbox-inline{padding-right:20px;padding-left:0}.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-right:10px;margin-left:0}.has-feedback .form-control{padding-left:42.5px;padding-right:12px}.form-control-feedback{left:0;right:auto}@media (min-width:768px){.form-inline label{padding-right:0;padding-left:auto}.form-inline .radio input[type=radio],.form-inline .checkbox input[type=checkbox]{margin-right:0;margin-left:auto}}@media (min-width:768px){.form-horizontal .control-label{text-align:left}}.form-horizontal .has-feedback .form-control-feedback{left:15px;right:auto}.caret{margin-right:2px;margin-left:0}.dropdown-menu{right:0;left:auto;float:left;text-align:right}.dropdown-menu.pull-right{left:0;right:auto;float:right}.dropdown-menu-right{left:auto;right:0}.dropdown-menu-left{left:0;right:auto}@media (min-width:768px){.navbar-right .dropdown-menu{left:auto;right:0}.navbar-right .dropdown-menu-left{left:0;right:auto}}.btn-group>.btn,.btn-group-vertical>.btn{float:right}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-right:-1px;margin-left:0}.btn-toolbar{margin-right:-5px;margin-left:0}.btn-toolbar .btn-group,.btn-toolbar .input-group{float:right}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-right:5px;margin-left:0}.btn-group>.btn:first-child{margin-right:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:4px;border-bottom-right-radius:4px;border-bottom-left-radius:0;border-top-left-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-top-left-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn-group{float:right}.btn-group.btn-group-justified>.btn,.btn-group.btn-group-justified>.btn-group{float:none}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child>.btn:last-child,.btn-group>.btn-group:first-child>.dropdown-toggle{border-top-right-radius:4px;border-bottom-right-radius:4px;border-bottom-left-radius:0;border-top-left-radius:0}.btn-group>.btn-group:last-child>.btn:first-child{border-top-left-radius:4px;border-bottom-left-radius:4px;border-bottom-right-radius:0;border-top-right-radius:0}.btn .caret{margin-right:0}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-right:0}.input-group .form-control{float:right}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group-btn:last-child>.btn-group:not(:last-child)>.btn{border-bottom-right-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:0;border-top-left-radius:0}.input-group-addon:first-child{border-right:1px solid #ccc;border-left:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:first-child>.btn-group:not(:first-child)>.btn{border-bottom-left-radius:4px;border-top-left-radius:4px;border-bottom-right-radius:0;border-top-right-radius:0}.input-group-addon:last-child{border-left:1px solid #ccc;border-right:0}.input-group-btn>.btn+.btn{margin-right:-1px;margin-left:auto}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-left:-1px;margin-right:auto}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{margin-right:-1px;margin-left:auto}.nav{padding-right:0;padding-left:auto}.nav-tabs>li{float:right}.nav-tabs>li>a{margin-left:auto;margin-right:-2px;border-radius:4px 4px 0 0}.nav-pills>li{float:none}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-right:2px;margin-left:auto}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-right:0;margin-left:auto}.nav-justified>.dropdown .dropdown-menu{right:auto}.nav-tabs-justified>li>a{margin-left:0;margin-right:auto}@media (min-width:768px){.nav-tabs-justified>li>a{border-radius:4px 4px 0 0}}@media (min-width:768px){.navbar-header{float:right}}.navbar-collapse{padding-right:15px;padding-left:15px}.navbar-brand{float:right}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-right:-15px;margin-left:auto}}.navbar-toggle{float:left;margin-left:15px;margin-right:auto}@media (max-width:767px){.navbar-nav .open .dropdown-menu>li>a,.navbar-nav .open .dropdown-menu .dropdown-header{padding:5px 25px 5px 15px}}@media (min-width:768px){.navbar-nav{float:right}.navbar-nav>li{float:right}.navbar-nav.navbar-right:last-child{margin-left:-15px;margin-right:auto}.navbar-nav.navbar-right.flip{float:left!important}.navbar-nav.navbar-right .dropdown-menu{left:0;right:auto}}@media (min-width:768px){.navbar-text{float:right}.navbar-text.navbar-right:last-child{margin-left:0;margin-right:auto}}.pagination{padding-right:0}.pagination>li>a,.pagination>li>span{float:right;margin-right:-1px;margin-left:0}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-bottom-right-radius:4px;border-top-right-radius:4px;border-bottom-left-radius:0;border-top-left-radius:0}.pagination>li:last-child>a,.pagination>li:last-child>span{margin-right:-1px;border-bottom-left-radius:4px;border-top-left-radius:4px;border-bottom-right-radius:0;border-top-right-radius:0}.pager{padding-right:0;padding-left:none}.pager .next>a,.pager .next>span{float:left}.pager .previous>a,.pager .previous>span{float:right}.nav-pills>li>a>.badge{margin-left:0;margin-right:3px}.alert-dismissable,.alert-dismissible{padding-left:35px;padding-right:15px}.alert-dismissable .close,.alert-dismissible .close{right:0;left:21}.progress-bar{float:right}.media>.pull-left{margin-right:10px}.media>.pull-left.flip{margin-right:0;margin-left:10px}.media>.pull-right{margin-left:10px}.media>.pull-right.flip{margin-left:0;margin-right:10px}.media-list{padding-right:0;padding-left:auto;list-style:none}.list-group{padding-right:0;padding-left:auto}.list-group-item>.badge{float:left}.list-group-item>.badge+.badge{margin-ight:5px;margin-left:auto}.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child{border-top-right-radius:3px;border-top-left-radius:0}.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child{border-top-left-radius:3px;border-top-right-radius:0}.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px;border-top-right-radius:0}.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px;border-top-left-radius:0}.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-right:0;border-left:none}.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:none;border-left:0}.embed-responsive .embed-responsive-item,.embed-responsive iframe,.embed-responsive embed,.embed-responsive object{right:0;left:none}.close{float:left}.modal-footer{text-align:left}.modal-footer .btn+.btn{margin-left:auto;margin-right:5px}.modal-footer .btn-group .btn+.btn{margin-right:-1px;margin-left:auto}.modal-footer .btn-block+.btn-block{margin-right:0;margin-left:auto}.popover{left:auto;text-align:right}.popover.top>.arrow{right:50%;left:auto;margin-right:-11px;margin-left:auto}.popover.top>.arrow:after{margin-right:-10px;margin-left:auto}.popover.bottom>.arrow{right:50%;left:auto;margin-right:-11px;margin-left:auto}.popover.bottom>.arrow:after{margin-right:-10px;margin-left:auto}.carousel-control{right:0;bottom:0}.carousel-control.left{right:auto;left:0;background-image:-webkit-linear-gradient(left,color-stop(rgba(0,0,0,.5)0),color-stop(rgba(0,0,0,.0001)100%));background-image:-o-linear-gradient(left,rgba(0,0,0,.5)0,rgba(0,0,0,.0001)100%);background-image:linear-gradient(to right,rgba(0,0,0,.5)0,rgba(0,0,0,.0001)100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1)}.carousel-control.right{left:auto;right:0;background-image:-webkit-linear-gradient(left,color-stop(rgba(0,0,0,.0001)0),color-stop(rgba(0,0,0,.5)100%));background-image:-o-linear-gradient(left,rgba(0,0,0,.0001)0,rgba(0,0,0,.5)100%);background-image:linear-gradient(to right,rgba(0,0,0,.0001)0,rgba(0,0,0,.5)100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1)}.carousel-control .icon-prev,.carousel-control .glyphicon-chevron-left{left:50%;right:auto;margin-right:-10px}.carousel-control .icon-next,.carousel-control .glyphicon-chevron-right{right:50%;left:auto;margin-left:-10px}.carousel-indicators{right:50%;left:0;margin-right:-30%;margin-left:0;padding-left:0}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:0;margin-right:-15px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-left:0;margin-right:-15px}.carousel-caption{left:20%;right:20%;padding-bottom:30px}}.pull-right.flip{float:left!important}.pull-left.flip{float:right!important}.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.has-success .form-control-feedback{color:#3c763d}.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-inline,.has-error .checkbox-inline{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.has-error .form-control-feedback{color:#a94442} \ No newline at end of file diff --git a/css/hesk_newStyle.php b/css/hesk_newStyle.php index 7884dd84..734aa36f 100644 --- a/css/hesk_newStyle.php +++ b/css/hesk_newStyle.php @@ -18,6 +18,14 @@ $questionMarkColor = $nuMods_settings['questionMarkColor']; ?> +.nu-rtlFloatLeft { + /* Don't do anything; the pager looks good already */ +} + +.nu-floatRight { + float: right; +} + .tabPadding { padding: 10px; } diff --git a/css/hesk_newStyleRTL.php b/css/hesk_newStyleRTL.php new file mode 100644 index 00000000..add02908 --- /dev/null +++ b/css/hesk_newStyleRTL.php @@ -0,0 +1,346 @@ + + +.nu-rtlFloatLeft { + float: left; +} + +.nu-floatRight { + float: left; +} + +.tabPadding { + padding: 10px; +} + +@media (max-width:991px) { + .close-ticket { + text-align: right; + } +} + +@media (min-width:992px) { + .close-ticket { + text-align: left; + } +} + + +@media (max-width:991px) { + .ticket-cell { + border-bottom: solid 1px #ddd; + border-left: 0; + padding-top: 5px; + } +} + +@media (max-width:991px) { + .ticket-cell-admin { + border-bottom: solid 1px #ddd; + border-left: 0; + padding-top: 5px; + height: 125px; + } +} + +@media (min-width:992px) { + .ticket-cell { + border-bottom: 0; + border-left: solid 1px #ddd; + margin-top: 1px; + height: 90px; + padding-top: 10px; + } +} + +@media (min-width:992px) { + .ticket-cell-admin { + border-bottom: 0; + border-left: solid 1px #ddd; + margin-top: 1px; + height: 125px; + padding-top: 10px; + } +} + +.row { + margin-right: 0px; + margin-left: 0px; +} + +.navbar { + margin-bottom: 0; +} +.navbar-default { + background-color: ; + background-image: none; + filter: none; +} +.navbar-default .navbar-brand { + color: ; +} +.navbar-default .navbar-brand:focus, .navbar-default .navbar-brand:hover { + color: ; + background-color: transparent; +} +.navbar-default .navbar-nav>li>a { + color: ; +} +.navbar-default .navbar-nav>li>a:focus, .navbar-default .navbar-nav>li>a:hover { + color: ; + background-color: transparent; +} +.dropdown-menu>li>a { + color: ; +} +.dropdown-menu>li>a:focus, .dropdown-menu>li>a:hover { + color: ; + text-decoration: none; + background-color: ; +} +.navbar-default .navbar-nav>.open>a, .navbar-default .navbar-nav>.open>a:focus, .navbar-default .navbar-nav>.open>a:hover { + color: ; + background-color: ; +} +.settingsquestionmark { + color: ; + font-size: 14px; +} +.settingsquestionmark:hover { + text-decoration: underline; +} +.h3questionmark { + color: ; + font-size: 14px; +} +.h3questionmark:hover { + text-decoration: underline; +} +.form-signin { + max-width: 330px; + padding: 15px; + margin: 0 auto; +} +.loginError { + width: 40%; + padding: 20px; + margin-right: auto; + margin-left: auto; +} +.kbContent { + padding-top: 10px; + text-align: right; +} +.withBorder { + border-bottom: 1px solid #ddd; +} +.ticketMessageContainer { + background-color: #ededef; + border: 1px solid #ddd; + margin-bottom: 20px; +} +.ticketName { + font-size: 20px; + font-weight: 300; + color: #000; + margin-top: 5px; +} +.ticketEmail { + font-size: 14px; + color: #888; +} +.ticketMessageTop { + padding-top: 10px; + padding-right: 10px; + padding-left: 10px; + margin-left: -15px; + color: #888; + background-color: #fff; +} + +.pushMargin { + margin-top: -10px; + margin-bottom: -10px; +} + +.pushMarginLeft { + margin-right: -15px; + margin-left: -15px; + padding-left: 0; +} + +.ticketMessageBottom { + padding-right: 10px; + padding-left: 10px; + margin-left: -15px; + word-wrap: break-word; + font-size: 15px; + background-color: #fff; +} +.ticketMessageBottom > p.message { + margin-bottom: 0px; + +} + +.ticketMessage { + margin-right: 238px; + background: #fff; + height: 100%; + position: relative; +} +.ticketPropertyTitle { + color: rgba(255, 255, 255, .75); + font-size: 11px; + text-transform: uppercase; +} +.ticketPropertyText { + font-size: 16px; + line-height: 1em; + color: #fff; +} +.criticalPriority { + background-color: red; +} +.highPriority { + background-color: #ff6a00; +} +.medLowPriority { + background-color: #8BB467; +} +div.blankSpace { + padding-top: 20px; +} +div.footerWithBorder { + border-top: 1px solid #cfd4d6; +} + +.blockRow > a:hover { + text-decoration: none; +} + +.block { + height: 114px; + width: 114px; + display: inline-block; + border: 1px solid #c9cfd7; + background-color: #fff; + border-radius: 4px; + font-size: .83em; + margin-left: 5px; + vertical-align: top; +} + +.block > .upper { + height:57px; + padding-top:10px; +} + +.block > .upper > img { + padding-top:5px; + padding-bottom:5px; + padding-right:41px; +} + +.block > .lower { + height:57px; + text-align:center; +} + +.block > .lower > p:hover { + text-decoration: underline; +} + +div.block:hover { + background-color: #e9ecef; +} +div.rightSideDash { + padding-right: 18px; + padding-left: 18px; +} +div.enclosing { + background-color: #fff; + color: #4a5571; + font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; + font-size: 12px; + width: 100%} +div.headersm { + width: 100%; + color: #fff; + font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; + font-size: 12px; + text-align: right; + background-color: #424b5c; + background-repeat: repeat-x; + padding: 12px 20px 8px; + margin: 0; + font-weight: 700; + padding-right: 20px; +} +div.installWarning { + width: 70%; + height: 52px; + margin-top: 10px; + margin-right: auto; + margin-left: auto; +} +div.setupContainer { + margin: 50px; + text-align: center; +} +div.setupLogo { + vertical-align: middle; + border: 0; + margin-top: -2px; +} +div.setupButtons { + text-decoration: none; + border: 4px solid #eee; + background: #fff; + border-radius: 5px; + color: #61718c; + -webkit-box-shadow: rgba(0, 0, 0, .1)0 0 3px; + -moz-box-shadow: rgba(0, 0, 0, .1)0 0 3px; + text-align: center; + margin: 20px 0; + padding: 10px 0; +} +.agreementBox { + position: relative; + background-color: #fff; + overflow: auto; + padding: 20px; + display: block; + height: 206px; + box-shadow: inset 0 0 4px #bbb, inset 0 0 20px #eee; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +.summaryList { + border-style: solid; + border-width: 1px; + border-color: #ddd; + border-top-color: transparent; +} +.installRequirements { + margin-right: auto; + margin-left: auto; + width: 90%; +} \ No newline at end of file diff --git a/hesk_style_v25RTL.css b/hesk_style_v25RTL.css new file mode 100644 index 00000000..a22825b3 --- /dev/null +++ b/hesk_style_v25RTL.css @@ -0,0 +1,745 @@ +body { + background-color: #f3fef4; + color: black; + font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; + font-size: 12px; + margin-right:0; + margin-left:0; + margin-top:0; + margin-bottom:0; +} + +table.enclosing { + background-color:#FFFFFF; + color : #4a5571; + font-family : Verdana, Geneva, Arial, Helvetica, sans-serif; + font-size: 12px; + width: 770px; +} + + +td { + color : #4a5571; + font-family : Verdana, Geneva, Arial, Helvetica, sans-serif; + font-size: 12px; + text-align: right; +} + +a img { + vertical-align: bottom; + border : none; +} + +td.white { + background-color: #FFFFFF; + color : #4a5571; + font-family : Verdana, Geneva, Arial, Helvetica, sans-serif; + font-size: 12px; +} + +td.admin_white { + background-color: #FFFFFF; + color : #4a5571; + font-family : Verdana, Geneva, Arial, Helvetica, sans-serif; + font-size: 11px; + border: #d1dceb 1px solid; + padding: 1px; +} + +td.admin_gray { + background-color: #f5fffa; + color : #4a5571; + font-family : Verdana, Geneva, Arial, Helvetica, sans-serif; + font-size: 11px; + border: #d1dceb 1px solid; + padding: 1px; +} + +td.notes { + background-color: #fffbf2; + color : #4a5571; + font-family : Verdana, Geneva, Arial, Helvetica, sans-serif; + font-size: 12px; + border: #ffe6b8 1px solid; +} + +th.tDetailsHead { + background-color: #F7F7F7; + color : #4a5571; + font-family : Verdana, Geneva, Arial, Helvetica, sans-serif; + font-size: 12px; + font-weight: normal; + text-align: center; +} + +td.tDetailsBody { + background-color: #FFFFFF; + color : #4a5571; + font-family : Verdana, Geneva, Arial, Helvetica, sans-serif; + font-size: 12px; + border: #F7F7F7 1px solid; + text-align: center; +} + +.small { + font-size: 11px; +} + +.smaller { + font-size: 10px; +} + +a { + color : Blue; + text-decoration : underline; +} + +a:hover { + color : Red; + text-decoration : none; +} + +table.white { + background-color: #ffffff ; + color : #23559C; + font-family : Verdana, Geneva, Arial, Helvetica, sans-serif; + font-size: 12px; + border-collapse: collapse; +} + +table.white th { + background-color: #ffffff; + color : #23559C; + font-family : Verdana, Geneva, Arial, Helvetica, sans-serif; + font-size: 11px; + border: #b2babd 1px solid; + border-collapse: collapse; + background-image: url(img/tableheader.jpg); + background-repeat: no-repeat; + background-position: right top; +} + +table.white th a { + color : #23559C; + font-family : Verdana, Geneva, Arial, Helvetica, sans-serif; + font-size: 11px; +} + +table.white td { + height: 25px; + padding-right: 5px; +} + +.noborder { +border: none; +} + +h3 { + color : #74804e; + font-family : Verdana, Geneva, Arial, Helvetica, sans-serif; + font-size: 13px; + font-weight: bold; + margin: 0px; +} + +.important { + color: Red; +} + +.medium { + color: #FF9900; +} + +input { + font-size: 12px; + font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; + color:#000000; +} + +input.button { + font-size: 12px; + font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; + color:#000000; + background-color:#FFFFFF; +} + +select { + font-size: 12px; + height: 20px; +} + +header a img {border: none; text-decoration: none !important;} + +.open {color : #FF0000;} +.waitingreply {color : #FF9933;} +.replied {color : #0000FF;} +.resolved {color : #008000;} +.allbutresolved {color : #000000;} + +.success {color : #008000;} +.error {color : #FF0000;} +.notice {color : #FF9900} + +#ok { + border: 1px solid #679800; +} + +#error { + border: 1px solid #ba3225; +} + +.rate { + color: #666666; + text-align: left; + font-style: italic; +} + +a.article { + color : Black; + text-decoration: none; + font-size: 11px; +} + +a.article:hover { + color : Red; + text-decoration : none; +} + +.article_list { + font-size: 11px; +} + +fieldset { + margin-bottom: 6px; + border: 1px SOLID #267DDC; + padding: 4px; + background-color:white; + position:relative; + display:block; + padding: 0px 10px 10px 10px; + margin:20px 0px 20px 0px; +} + +legend { + background-image: url(img/bluebtn.png); + background-repeat: no-repeat; + color: #172901; + border: 1px solid #267DDC; + height: 10px; + font-size: 10px; + font-weight:bold; + font-family : Verdana, Geneva, Arial, Helvetica, sans-serif; + background-position: right top; + display:block; + width: auto; + padding:4px 5px; + margin:0px 0px 10px 0px; + position:relative; + top: -12px; + width:130px; +} + +/*newly introduced styles (version 2.0)*/ + +.header { + width: 100%; + background-color: #74a62b; + color : #ffffff; + font-family : Verdana, Geneva, Arial, Helvetica, sans-serif; + font-size: 11px; + text-align: center; + background-image: url(img/header.png); + background-repeat: repeat-x; + height: 57px; + padding: 0px; + margin: 0px; +} + +.header td { +text-align: center; +vertical-align: middle; +color:#FFFFFF; +} +.header a, .header a:link, .header a:active, .header a:visited { + color : #ffffff; + font-family : Verdana, Geneva, Arial, Helvetica, sans-serif; + font-size: 11px; + text-align: center; +} +.header a:hover {} + +.headersm { + width: 100%; + background-color: #669933; + color : #ffffff; + font-family : Verdana, Geneva, Arial, Helvetica, sans-serif; + font-size: 12px; + text-align: right; + background-image: url(img/headerbgsm.jpg); + background-repeat: repeat-x; + height: 25px; + padding: 0px; + margin: 0px; + font-weight:bold; + padding-right: 20px; +} + +hr { + border: none; + border-bottom: 1px dotted #adbac3; + width: 100%; + padding-top: 10px; + margin-bottom: 10px; + height: 1px; +} + +.greenbutton { + background-image: url(img/greenbtn.jpg); + background-repeat: no-repeat; + text-align: center; + color: #FFFFFF; + border: 1px solid #527234; + font-size: 10px; + font-weight:bold; + font-family : Verdana, Geneva, Arial, Helvetica, sans-serif; + background-position: right top; + height: 19px; + padding-right: 6px; + padding-left: 6px; + margin-right: 2px; + margin-left: 2px +} + +.greenbuttonover { + background-image: url(img/greenbtnover.gif); + background-repeat: no-repeat; + text-align: center; + color: #FFFFFF; + border: 1px solid #527234; + font-size: 10px; + font-weight:bold; + font-family : Verdana, Geneva, Arial, Helvetica, sans-serif; + background-position: right top; + height: 19px; + padding-right: 6px; + padding-left: 6px; + margin-right: 2px; + margin-left: 2px +} + +.orangebutton { + background-image: url(img/orangebtn.jpg); + background-repeat: no-repeat; + text-align: center; + color: #660000; + border: 1px solid #bf6628; + height: 20px; + font-size: 10px; + font-weight:bold; + font-family : Verdana, Geneva, Arial, Helvetica, sans-serif; + background-position: right top; + padding-right: 6px; + padding-left: 6px; + margin-right: 2px; + margin-left: 2px; + text-decoration: none; + margin-top: 0px; +} + +.orangebuttonover { + background-image: url(img/orangebtnover.gif); + background-repeat: no-repeat; + text-align: center; + color: #660000; + border: 1px solid #bf6628; + height: 20px; + font-size: 10px; + font-weight:bold; + font-family : Verdana, Geneva, Arial, Helvetica, sans-serif; + background-position: right top; + padding-right: 6px; + padding-left: 6px; + margin-right: 2px; + margin-left: 2px; + text-decoration: none; + margin-top: 0px; +} + +.bluebutton { + background-image: url(img/bluebtn.png); + background-repeat: no-repeat; + text-align: center; + color: #660000; + border: 1px solid #5b79a3; + height: 20px; + font-size: 10px; + font-weight:bold; + font-family : Verdana, Geneva, Arial, Helvetica, sans-serif; + background-position: right top; + padding-right: 6px; + padding-left: 6px; + margin-right: 2px; + text-decoration: none; + margin-left: 2px; + padding-top: 2px; +} + + +/*styles for roundcorners tables*/ + +.roundcornersleft { + width: 7px; + background-image: url(img/roundcornerslm.jpg); + background-repeat: repeat-y; + background-position: right; +} +.roundcornersright { + width: 7px; + background-image: url(img/roundcornersrm.jpg); + background-repeat: repeat-y; + background-position: left; +} +.roundcornerstop { + height: 7px; + background-image: url(img/roundcornerst.jpg); + background-repeat: repeat-x; + background-position: top; +} +.roundcornersbottom { + height: 7px; + background-image: url(img/roundcornersb.jpg); + background-repeat: repeat-x; + background-position: bottom; +} +.ticketrow { + background-color: #f5fffa; + color : #4a5571; + font-family : Verdana, Geneva, Arial, Helvetica, sans-serif; + font-size: 12px; + border: #748aaf 1px dotted; + padding: 6px; +} +.ticketalt { + background-color: #ffffff; + color : #4a5571; + font-family : Verdana, Geneva, Arial, Helvetica, sans-serif; + font-size: 12px; + padding: 6px; +} + +.tickettd { + font-family : Verdana, Geneva, Arial, Helvetica, sans-serif; + font-size: 12px; +} + +.subheaderrow { + background-color: #ffffff; + color : #23559C; + border: #23559C solid 1px; + font-family : Verdana, Geneva, Arial, Helvetica, sans-serif; + font-size: 11px; + border-collapse: collapse; + background-image: url(img/tableheader.jpg); + background-repeat: no-repeat; + background-position: right top; + height: 25px; + padding-right: 20px; + padding-left: 20px; + padding-top: 5px; + } + +.homepageh3, .section { + color: #74804e; + font-weight: bold; +} + +/*newly introduced styles (version 2.2)*/ + +.large { + font-size:14px; +} + +.largebold { + font-size:14px; + font-weight:bold; +} + +.assignedyou { + color: red; +} + +.assignedother { + color: green; +} + +div.error { + border: 1px solid #cd0a0a; + background: #fef1ec; + color: #cd0a0a; + padding: 10px; +} + +div.success { + border: 1px solid #18760f; + background: #e9ffdb; + color: #363636; + padding: 10px; +} + +div.notice { + border: 1px solid #fcefa1; + background: #fbf9ee; + color: #363636; + padding: 10px; + vertical-align: middle; +} + +.admin_green { + background-color: #e3ffd0; + font-weight: bold; +} + +.admin_red { + background-color: #fef1ec; + font-weight: bold; +} + +.borderBottom { + border-bottom: silver 1px dashed; +} + +.borderTop { + border-top: silver 1px dashed; +} + +.alignTop { + vertical-align: top; +} + +.alignMiddle { + vertical-align: middle; +} + +.alignBottom { + vertical-align: bottom; +} + +hr.dashed { + border: none 0; + border-top: 1px dashed silver; + height: 1px; +} + +/* newly introduced styles (version 2.3) */ + +h1 { + color : #74804e; + font-family : Verdana, Geneva, Arial, Helvetica, sans-serif; + font-size: 13px; + font-weight: bold; + margin: 0px; +} + +.critical { + color: #9400d3; + font-weight: bold; +} + +td.admin_critical { + background-color: #fff0ff; + color : #000000; + font-family : Verdana, Geneva, Arial, Helvetica, sans-serif; + font-size: 11px; + border: 1px solid #ff66ff; + border-top: 2px dashed #ff66ff; + padding: 1px; +} + +.isError { + color: black; + background-color: #fff9f7; + border: 1px solid red; +} + +.isNotice { + color: black; + border: 1px solid orange; + background: #fbf9ee; +} + +.optionWhiteON{ + padding:2px; + border:1px dotted silver; + background-color: #b0e0e6; +} + +.optionWhiteOFF { + padding:2px; + border:1px dotted silver; + background-color: white; +} + +.optionBlueON { + padding:2px; + border:1px dotted gray; + background-color: #b0e0e6; +} + +.optionBlueOFF { + padding:2px; + border:1px dotted gray; + background-color: #f5fffa; +} + +.optionWhiteNbON{ + border: none; + background-color: #b0e0e6; + vertical-align: text-bottom; +} + +.optionWhiteNbOFF { + border: none; + background-color: white; + vertical-align: text-bottom; +} + +.kbCatListON { + background-color: #fcefa1; +} + +.kbCatListOFF { + background-color: white; +} + +div.progress-container { + border: 1px solid #ccc; + width: 100px; + margin: 2px 0 2px 5px; + padding: 1px; + float: right; + background: white; +} + +div.progress-container > div { + background-color: #ACE97C; + height: 12px +} + +.black {color: black;} +.inprogress {color : #006400;} +.onhold {color : #000000;} + +div.online { + border: 1px solid #e5e8ff; + background: #ffffff; + color: #000000; + padding: 0px; + vertical-align: middle; +} + +span.online { + font-size: 10px; + white-space:nowrap; +} + +/* newly introduced styles (version 2.4) */ + +.orangebuttonsec { + background-image: url(img/orangebtnsec.jpg); + background-repeat: no-repeat; + text-align: center; + color: #660000; + border: 1px solid #bf6628; + height: 20px; + font-size: 10px; + font-weight:normal; + font-family : Verdana, Geneva, Arial, Helvetica, sans-serif; + background-position: right top; + padding-right: 6px; + padding-left: 6px; + margin-right: 2px; + margin-left: 2px; + text-decoration: none; + margin-top: 0px; +} + +.orangebuttonsecover { + background-image: url(img/orangebtnover.gif); + background-repeat: no-repeat; + text-align: center; + color: #660000; + border: 1px solid #bf6628; + height: 20px; + font-size: 10px; + font-weight:normal; + font-family : Verdana, Geneva, Arial, Helvetica, sans-serif; + background-position: right top; + padding-right: 6px; + padding-left: 6px; + margin-right: 2px; + margin-left: 2px; + text-decoration: none; + margin-top: 0px; +} + +td.admin_yellow { + background-color: #ffffe0; + color : #4a5571; + font-family : Verdana, Geneva, Arial, Helvetica, sans-serif; + font-size: 11px; + border: #d1dceb 1px solid; + padding: 1px; +} + +/* New styles in HESK version 2.5 */ + +.kb_published { + color: #009900; +} + +.kb_private { + color: #4a5571; +} + +.kb_draft { + color: #cc9933; +} + +.searchbutton { + cursor:pointer; + width:70px; + height:27px; + text-indent:-999px; + text-transform: capitalize; + color: transparent; + background: url(img/ico-search.png) no-repeat #4d90fe center; + border: 1px solid #3079ED; + -moz-border-radius: 2px; + -webkit-border-radius: 2px; +} + +.searchbutton:hover { + background: url(img/ico-search.png) no-repeat center #357AE8; + border: 1px solid #2F5BB7; +} + +.searchfield { + width:400px; + height:21px; + font-size:14px; + text-indent:2px; + vertical-align: bottom; +} + +.sbsmall { + width:50px; + height:22px; + margin-top:2px; +} + +.sfsmall { + width:200px; + height:16px; + font-size:12px; + margin-top:2px; +} \ No newline at end of file diff --git a/inc/header.inc.php b/inc/header.inc.php index 2d322a61..25185f13 100644 --- a/inc/header.inc.php +++ b/inc/header.inc.php @@ -34,6 +34,7 @@ /* Check if this is a valid include */ if (!defined('IN_SCRIPT')) {die('Invalid attempt');} +require(HESK_PATH . 'nuMods_settings.inc.php'); ?> @@ -41,10 +42,19 @@ if (!defined('IN_SCRIPT')) {die('Invalid attempt');} <?php echo (isset($hesk_settings['tmp_title']) ? $hesk_settings['tmp_title'] : $hesk_settings['hesk_title']); ?> + + + + - + + + + + + diff --git a/inc/headerAdmin.inc.php b/inc/headerAdmin.inc.php index c7786a3c..1c462398 100644 --- a/inc/headerAdmin.inc.php +++ b/inc/headerAdmin.inc.php @@ -34,6 +34,7 @@ /* Check if this is a valid include */ if (!defined('IN_SCRIPT')) {die('Invalid attempt');} +require(HESK_PATH . 'nuMods_settings.inc.php'); ?> @@ -41,10 +42,19 @@ if (!defined('IN_SCRIPT')) {die('Invalid attempt');} <?php echo (isset($hesk_settings['tmp_title']) ? $hesk_settings['tmp_title'] : $hesk_settings['hesk_title']); ?> + + + + - + + + + + + diff --git a/inc/knowledgebase_functions.inc.php b/inc/knowledgebase_functions.inc.php index 52cd71ee..1796c358 100644 --- a/inc/knowledgebase_functions.inc.php +++ b/inc/knowledgebase_functions.inc.php @@ -91,7 +91,7 @@ function hesk_kbTopArticles($how_many, $index = 1) ?> -

    +

    @@ -107,7 +107,7 @@ function hesk_kbTopArticles($how_many, $index = 1) /* Show number of views? */ if ($hesk_settings['kb_views'] && hesk_dbNumRows($res) != 0) { - echo ''; + echo ''; } ?> @@ -124,7 +124,7 @@ function hesk_kbTopArticles($how_many, $index = 1) /* If no results found end here */ if (hesk_dbNumRows($res) == 0) { - echo '

    '.$hesklang['noa'].'
     

    '; + echo '

    '.$hesklang['noa'].'
     

    '; return true; } @@ -147,7 +147,7 @@ function hesk_kbTopArticles($how_many, $index = 1) if ($hesk_settings['kb_views']) { - echo ''; + echo ''; } echo ' @@ -201,7 +201,7 @@ function hesk_kbLatestArticles($how_many, $index = 1) } ?> -

    +

    ' . $hesklang['views'] . '' . $hesklang['views'] . '' . $article['views'] . '' . $article['views'] . '
    @@ -216,7 +216,7 @@ function hesk_kbLatestArticles($how_many, $index = 1) /* Show number of views? */ if ($hesk_settings['kb_date'] && hesk_dbNumRows($res) != 0) { - echo ''; + echo ''; } ?> @@ -233,7 +233,7 @@ function hesk_kbLatestArticles($how_many, $index = 1) /* If no results found end here */ if (hesk_dbNumRows($res) == 0) { - echo '

    '.$hesklang['noa'].'
     

    '; + echo '

    '.$hesklang['noa'].'
     

    '; return true; } @@ -256,7 +256,7 @@ function hesk_kbLatestArticles($how_many, $index = 1) if ($hesk_settings['kb_date']) { - echo ''; + echo ''; } echo ' @@ -333,7 +333,7 @@ function hesk_kbSearchSmall() } ?> - - - + + Date: Fri, 12 Sep 2014 00:02:20 -0400 Subject: [PATCH 046/208] #35 Added auto-refresh property to the users table --- admin/profile.php | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/admin/profile.php b/admin/profile.php index 1971b542..8a75d308 100644 --- a/admin/profile.php +++ b/admin/profile.php @@ -228,11 +228,11 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php'); +

    -

    @@ -257,6 +257,14 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
    +
    + +
    + + + Enter value in milliseconds, or 0 to disable. No fractional values. +
    +

    @@ -394,6 +402,9 @@ function update_profile() { /* Auto-start ticket timer */ $_SESSION['new']['autostart'] = isset($_POST['autostart']) ? 1 : 0; + /* Update auto-refresh time */ + $_SESSION['new']['autorefresh'] = isset($_POST['autorefresh']) ? $_POST['autorefresh'] : 0; + /* Notifications */ $_SESSION['new']['notify_new_unassigned'] = empty($_POST['notify_new_unassigned']) || ! $can_view_unassigned ? 0 : 1; $_SESSION['new']['notify_new_my'] = empty($_POST['notify_new_my']) ? 0 : 1; @@ -415,6 +426,7 @@ function update_profile() { else { /* Update database */ + //TODO Add auto-refresh to the update SQL hesk_dbQuery( "UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."users` SET `name`='".hesk_dbEscape($_SESSION['new']['name'])."', @@ -424,6 +436,7 @@ function update_profile() { $sql_pass , `afterreply`='".intval($_SESSION['new']['afterreply'])."' , `autostart`='".intval($_SESSION['new']['autostart'])."' , + `autorefresh`='".intval($_SESSION['new']['autorefresh'])."' , `notify_new_unassigned`='".intval($_SESSION['new']['notify_new_unassigned'])."' , `notify_new_my`='".intval($_SESSION['new']['notify_new_my'])."' , `notify_reply_unassigned`='".intval($_SESSION['new']['notify_reply_unassigned'])."' , From e4744829ac762f9b467fefcc2db7f6a256aad51e Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 14 Sep 2014 00:44:06 -0400 Subject: [PATCH 047/208] #35 Update install scripts for auto-refresh --- install/install_functions.inc.php | 2 +- install/updateNuMods.php | 6 +- install/updateTo1-2-4.php | 223 ------------------------------ install/updateTo1-3-1.php | 11 ++ 4 files changed, 15 insertions(+), 227 deletions(-) delete mode 100644 install/updateTo1-2-4.php create mode 100644 install/updateTo1-3-1.php diff --git a/install/install_functions.inc.php b/install/install_functions.inc.php index 2f6682fb..35a73f73 100644 --- a/install/install_functions.inc.php +++ b/install/install_functions.inc.php @@ -37,7 +37,7 @@ if (!defined('IN_SCRIPT')) {die('Invalid attempt');} // We will be installing this HESK version: define('HESK_NEW_VERSION','2.5.5'); -define('NUMODS_NEW_VERSION','1.2.4'); +define('NUMODS_NEW_VERSION','1.3.1'); // Other required files and settings define('INSTALL',1); diff --git a/install/updateNuMods.php b/install/updateNuMods.php index 4c435213..d8bafd96 100644 --- a/install/updateNuMods.php +++ b/install/updateNuMods.php @@ -65,9 +65,9 @@ if ($_GET['update'] == 1)
    -

    Update NuMods from v1.2.0 - v1.2.3 to v1.2.4

    -

    If you have NuMods v1.2.0 - v1.2.3, click here to update to v1.2.4. Do not use the installation below!

    -

    Install NuMods v1.2.4 from a version before 1.2.0

    +

    Update NuMods from v1.2.4 - v1.3.0 to v1.3.1

    +

    Update here. Do not use the installation below!

    +

    Install NuMods v1.3.1 for the first time

    If you have not yet installed/updated HESK, please do so first before continuing; otherwise installation will fail!


    Please verify the database information below. Addtionally, ensure that the database user has CREATE permissions.

    diff --git a/install/updateTo1-2-4.php b/install/updateTo1-2-4.php deleted file mode 100644 index 7be61d3a..00000000 --- a/install/updateTo1-2-4.php +++ /dev/null @@ -1,223 +0,0 @@ - - -NOTICE: You already have version 1.2.3 (Hesk version ' . HESK_NEW_VERSION . ') installed. - -'); -} - -if ($hesk_settings['hesk_version'] != HESK_OLD_VERSION) -{ -die(' -
    -
    -ERROR: You do not have version 1.2.3 (Hesk version ' . HESK_OLD_VERSION . ')
    -
    -This patch may only be used with NuMods version 1.2.3 (Hesk version ' . HESK_OLD_VERSION . '), your HESK version is ' . $hesk_settings['hesk_version'] . '
    -
    -You should Download full version ' . HESK_NEW_VERSION .' instead, and NuMods from http://numods.mkochcs.com.
    -
    -
    '); -} - -define('HIDE_ONLINE',1); - -/* Debugging should be enabled in installation mode */ -$hesk_settings['debug_mode'] = 1; -error_reporting(E_ALL); -$__maindir = dirname(dirname(__FILE__)) . '/'; - -hesk_iHeader(); -?> -
    - -
    -
    ' . $hesklang['dta'] . '' . $hesklang['dta'] . '' . hesk_date($article['dt'], true) . '' . hesk_date($article['dt'], true) . ' +
    diff --git a/inc/show_search_form.inc.php b/inc/show_search_form.inc.php index e878913a..ea727e78 100644 --- a/inc/show_search_form.inc.php +++ b/inc/show_search_form.inc.php @@ -323,11 +323,11 @@ $more2 = empty($_GET['more2']) ? 0 : 1; - - - +
    +
    />
    +
    :  
    diff --git a/inc/ticket_list.inc.php b/inc/ticket_list.inc.php index 33e2033a..8a15307c 100644 --- a/inc/ticket_list.inc.php +++ b/inc/ticket_list.inc.php @@ -122,7 +122,7 @@ if ($total > 0) /* List pages */ echo '
    -
    +
      '; if ($pages > 7) { @@ -166,7 +166,7 @@ if ($total > 0) } echo '
    -
    +
    '.$hesklang['jump_page'].'
    + @@ -477,7 +477,7 @@ function hesk_show_kb_category($catid, $is_search = 0) { } // END if NumRows > 0 ?> -

    +

    diff --git a/nuMods_settings.inc.php b/nuMods_settings.inc.php index 4a20313d..855c65db 100644 --- a/nuMods_settings.inc.php +++ b/nuMods_settings.inc.php @@ -13,5 +13,8 @@ $nuMods_settings['dropdownItemTextHoverColor'] = '#262626'; $nuMods_settings['dropdownItemTextHoverBackgroundColor'] = '#f5f5f5'; $nuMods_settings['questionMarkColor'] = '#000000'; +//-- Set this to 1 for right-to-left text. EXPERIMENTAL! +$nuMods_settings['rtl'] = 0; + /* DO NOT EDIT ANYTHING BELOW THIS LINE */ $nuMods_settings['version']='1.2.4'; diff --git a/print.php b/print.php index 51ea7404..a10b4f24 100644 --- a/print.php +++ b/print.php @@ -37,6 +37,7 @@ define('HESK_PATH','./'); /* Get all the required files and functions */ require(HESK_PATH . 'hesk_settings.inc.php'); +require(HESK_PATH . 'nuMods_settings.inc.php'); require(HESK_PATH . 'inc/common.inc.php'); hesk_load_database_functions(); @@ -110,7 +111,7 @@ hr background-color: #9e9e9e; height: 1px; width: 100%; - text-align: left; + text-align: ; } diff --git a/ticket.php b/ticket.php index 6b5a7aeb..31777aa2 100644 --- a/ticket.php +++ b/ticket.php @@ -520,7 +520,7 @@ function hesk_printCustomerReplyForm($reopen=0) ?> -

    +

    @@ -538,7 +538,7 @@ function hesk_printCustomerReplyForm($reopen=0) ?>
    -
    +
    Date: Sun, 7 Sep 2014 22:08:07 -0400 Subject: [PATCH 033/208] #42 Started on adding icons to areas of the help desk --- admin/index.php | 2 +- css/octicons.css | 235 ++++++++++++++++++++++++++++++++++++++++ css/octicons.eot | Bin 0 -> 31440 bytes css/octicons.svg | 198 +++++++++++++++++++++++++++++++++ fonts/octicons.ttf | Bin 0 -> 31272 bytes fonts/octicons.woff | Bin 0 -> 17492 bytes inc/header.inc.php | 15 ++- inc/headerAdmin.inc.php | 5 + nuMods_settings.inc.php | 3 + 9 files changed, 452 insertions(+), 6 deletions(-) create mode 100644 css/octicons.css create mode 100644 css/octicons.eot create mode 100644 css/octicons.svg create mode 100644 fonts/octicons.ttf create mode 100644 fonts/octicons.woff diff --git a/admin/index.php b/admin/index.php index 0ee24e7e..f37414a2 100644 --- a/admin/index.php +++ b/admin/index.php @@ -279,7 +279,7 @@ function print_login()
    -
    +
    ';} else { echo '
    ';}?>
    diff --git a/css/octicons.css b/css/octicons.css new file mode 100644 index 00000000..d1208a05 --- /dev/null +++ b/css/octicons.css @@ -0,0 +1,235 @@ +@font-face { + font-family: 'octicons'; + src: url('octicons.eot?#iefix') format('embedded-opentype'), + url('../fonts/octicons.woff') format('woff'), + url('../fonts/octicons.ttf') format('truetype'), + url('octicons.svg#octicons') format('svg'); + font-weight: normal; + font-style: normal; +} + +/* + +.octicon is optimized for 16px. +.mega-octicon is optimized for 32px but can be used larger. + +*/ +.octicon, .mega-octicon { + font: normal normal normal 16px/1 octicons; + display: inline-block; + text-decoration: none; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +.mega-octicon { font-size: 32px; } + + +.octicon-alert:before { content: '\f02d'} /*  */ +.octicon-alignment-align:before { content: '\f08a'} /*  */ +.octicon-alignment-aligned-to:before { content: '\f08e'} /*  */ +.octicon-alignment-unalign:before { content: '\f08b'} /*  */ +.octicon-arrow-down:before { content: '\f03f'} /*  */ +.octicon-arrow-left:before { content: '\f040'} /*  */ +.octicon-arrow-right:before { content: '\f03e'} /*  */ +.octicon-arrow-small-down:before { content: '\f0a0'} /*  */ +.octicon-arrow-small-left:before { content: '\f0a1'} /*  */ +.octicon-arrow-small-right:before { content: '\f071'} /*  */ +.octicon-arrow-small-up:before { content: '\f09f'} /*  */ +.octicon-arrow-up:before { content: '\f03d'} /*  */ +.octicon-beer:before { content: '\f069'} /*  */ +.octicon-book:before { content: '\f007'} /*  */ +.octicon-bookmark:before { content: '\f07b'} /*  */ +.octicon-briefcase:before { content: '\f0d3'} /*  */ +.octicon-broadcast:before { content: '\f048'} /*  */ +.octicon-browser:before { content: '\f0c5'} /*  */ +.octicon-bug:before { content: '\f091'} /*  */ +.octicon-calendar:before { content: '\f068'} /*  */ +.octicon-check:before { content: '\f03a'} /*  */ +.octicon-checklist:before { content: '\f076'} /*  */ +.octicon-chevron-down:before { content: '\f0a3'} /*  */ +.octicon-chevron-left:before { content: '\f0a4'} /*  */ +.octicon-chevron-right:before { content: '\f078'} /*  */ +.octicon-chevron-up:before { content: '\f0a2'} /*  */ +.octicon-circle-slash:before { content: '\f084'} /*  */ +.octicon-circuit-board:before { content: '\f0d6'} /*  */ +.octicon-clippy:before { content: '\f035'} /*  */ +.octicon-clock:before { content: '\f046'} /*  */ +.octicon-cloud-download:before { content: '\f00b'} /*  */ +.octicon-cloud-upload:before { content: '\f00c'} /*  */ +.octicon-code:before { content: '\f05f'} /*  */ +.octicon-color-mode:before { content: '\f065'} /*  */ +.octicon-comment-add:before, +.octicon-comment:before { content: '\f02b'} /*  */ +.octicon-comment-discussion:before { content: '\f04f'} /*  */ +.octicon-credit-card:before { content: '\f045'} /*  */ +.octicon-dash:before { content: '\f0ca'} /*  */ +.octicon-dashboard:before { content: '\f07d'} /*  */ +.octicon-database:before { content: '\f096'} /*  */ +.octicon-device-camera:before { content: '\f056'} /*  */ +.octicon-device-camera-video:before { content: '\f057'} /*  */ +.octicon-device-desktop:before { content: '\f27c'} /*  */ +.octicon-device-mobile:before { content: '\f038'} /*  */ +.octicon-diff:before { content: '\f04d'} /*  */ +.octicon-diff-added:before { content: '\f06b'} /*  */ +.octicon-diff-ignored:before { content: '\f099'} /*  */ +.octicon-diff-modified:before { content: '\f06d'} /*  */ +.octicon-diff-removed:before { content: '\f06c'} /*  */ +.octicon-diff-renamed:before { content: '\f06e'} /*  */ +.octicon-ellipsis:before { content: '\f09a'} /*  */ +.octicon-eye-unwatch:before, +.octicon-eye-watch:before, +.octicon-eye:before { content: '\f04e'} /*  */ +.octicon-file-binary:before { content: '\f094'} /*  */ +.octicon-file-code:before { content: '\f010'} /*  */ +.octicon-file-directory:before { content: '\f016'} /*  */ +.octicon-file-media:before { content: '\f012'} /*  */ +.octicon-file-pdf:before { content: '\f014'} /*  */ +.octicon-file-submodule:before { content: '\f017'} /*  */ +.octicon-file-symlink-directory:before { content: '\f0b1'} /*  */ +.octicon-file-symlink-file:before { content: '\f0b0'} /*  */ +.octicon-file-text:before { content: '\f011'} /*  */ +.octicon-file-zip:before { content: '\f013'} /*  */ +.octicon-flame:before { content: '\f0d2'} /*  */ +.octicon-fold:before { content: '\f0cc'} /*  */ +.octicon-gear:before { content: '\f02f'} /*  */ +.octicon-gift:before { content: '\f042'} /*  */ +.octicon-gist:before { content: '\f00e'} /*  */ +.octicon-gist-secret:before { content: '\f08c'} /*  */ +.octicon-git-branch-create:before, +.octicon-git-branch-delete:before, +.octicon-git-branch:before { content: '\f020'} /*  */ +.octicon-git-commit:before { content: '\f01f'} /*  */ +.octicon-git-compare:before { content: '\f0ac'} /*  */ +.octicon-git-merge:before { content: '\f023'} /*  */ +.octicon-git-pull-request-abandoned:before, +.octicon-git-pull-request:before { content: '\f009'} /*  */ +.octicon-globe:before { content: '\f0b6'} /*  */ +.octicon-graph:before { content: '\f043'} /*  */ +.octicon-heart:before { content: '\2665'} /* ♥ */ +.octicon-history:before { content: '\f07e'} /*  */ +.octicon-home:before { content: '\f08d'} /*  */ +.octicon-horizontal-rule:before { content: '\f070'} /*  */ +.octicon-hourglass:before { content: '\f09e'} /*  */ +.octicon-hubot:before { content: '\f09d'} /*  */ +.octicon-inbox:before { content: '\f0cf'} /*  */ +.octicon-info:before { content: '\f059'} /*  */ +.octicon-issue-closed:before { content: '\f028'} /*  */ +.octicon-issue-opened:before { content: '\f026'} /*  */ +.octicon-issue-reopened:before { content: '\f027'} /*  */ +.octicon-jersey:before { content: '\f019'} /*  */ +.octicon-jump-down:before { content: '\f072'} /*  */ +.octicon-jump-left:before { content: '\f0a5'} /*  */ +.octicon-jump-right:before { content: '\f0a6'} /*  */ +.octicon-jump-up:before { content: '\f073'} /*  */ +.octicon-key:before { content: '\f049'} /*  */ +.octicon-keyboard:before { content: '\f00d'} /*  */ +.octicon-law:before { content: '\f0d8'} /* */ +.octicon-light-bulb:before { content: '\f000'} /*  */ +.octicon-link:before { content: '\f05c'} /*  */ +.octicon-link-external:before { content: '\f07f'} /*  */ +.octicon-list-ordered:before { content: '\f062'} /*  */ +.octicon-list-unordered:before { content: '\f061'} /*  */ +.octicon-location:before { content: '\f060'} /*  */ +.octicon-gist-private:before, +.octicon-mirror-private:before, +.octicon-git-fork-private:before, +.octicon-lock:before { content: '\f06a'} /*  */ +.octicon-logo-github:before { content: '\f092'} /*  */ +.octicon-mail:before { content: '\f03b'} /*  */ +.octicon-mail-read:before { content: '\f03c'} /*  */ +.octicon-mail-reply:before { content: '\f051'} /*  */ +.octicon-mark-github:before { content: '\f00a'} /*  */ +.octicon-markdown:before { content: '\f0c9'} /*  */ +.octicon-megaphone:before { content: '\f077'} /*  */ +.octicon-mention:before { content: '\f0be'} /*  */ +.octicon-microscope:before { content: '\f089'} /*  */ +.octicon-milestone:before { content: '\f075'} /*  */ +.octicon-mirror-public:before, +.octicon-mirror:before { content: '\f024'} /*  */ +.octicon-mortar-board:before { content: '\f0d7'} /* */ +.octicon-move-down:before { content: '\f0a8'} /*  */ +.octicon-move-left:before { content: '\f074'} /*  */ +.octicon-move-right:before { content: '\f0a9'} /*  */ +.octicon-move-up:before { content: '\f0a7'} /*  */ +.octicon-mute:before { content: '\f080'} /*  */ +.octicon-no-newline:before { content: '\f09c'} /*  */ +.octicon-octoface:before { content: '\f008'} /*  */ +.octicon-organization:before { content: '\f037'} /*  */ +.octicon-package:before { content: '\f0c4'} /*  */ +.octicon-paintcan:before { content: '\f0d1'} /*  */ +.octicon-pencil:before { content: '\f058'} /*  */ +.octicon-person-add:before, +.octicon-person-follow:before, +.octicon-person:before { content: '\f018'} /*  */ +.octicon-pin:before { content: '\f041'} /*  */ +.octicon-playback-fast-forward:before { content: '\f0bd'} /*  */ +.octicon-playback-pause:before { content: '\f0bb'} /*  */ +.octicon-playback-play:before { content: '\f0bf'} /*  */ +.octicon-playback-rewind:before { content: '\f0bc'} /*  */ +.octicon-plug:before { content: '\f0d4'} /*  */ +.octicon-repo-create:before, +.octicon-gist-new:before, +.octicon-file-directory-create:before, +.octicon-file-add:before, +.octicon-plus:before { content: '\f05d'} /*  */ +.octicon-podium:before { content: '\f0af'} /*  */ +.octicon-primitive-dot:before { content: '\f052'} /*  */ +.octicon-primitive-square:before { content: '\f053'} /*  */ +.octicon-pulse:before { content: '\f085'} /*  */ +.octicon-puzzle:before { content: '\f0c0'} /*  */ +.octicon-question:before { content: '\f02c'} /*  */ +.octicon-quote:before { content: '\f063'} /*  */ +.octicon-radio-tower:before { content: '\f030'} /*  */ +.octicon-repo-delete:before, +.octicon-repo:before { content: '\f001'} /*  */ +.octicon-repo-clone:before { content: '\f04c'} /*  */ +.octicon-repo-force-push:before { content: '\f04a'} /*  */ +.octicon-gist-fork:before, +.octicon-repo-forked:before { content: '\f002'} /*  */ +.octicon-repo-pull:before { content: '\f006'} /*  */ +.octicon-repo-push:before { content: '\f005'} /*  */ +.octicon-rocket:before { content: '\f033'} /*  */ +.octicon-rss:before { content: '\f034'} /*  */ +.octicon-ruby:before { content: '\f047'} /*  */ +.octicon-screen-full:before { content: '\f066'} /*  */ +.octicon-screen-normal:before { content: '\f067'} /*  */ +.octicon-search-save:before, +.octicon-search:before { content: '\f02e'} /*  */ +.octicon-server:before { content: '\f097'} /*  */ +.octicon-settings:before { content: '\f07c'} /*  */ +.octicon-log-in:before, +.octicon-sign-in:before { content: '\f036'} /*  */ +.octicon-log-out:before, +.octicon-sign-out:before { content: '\f032'} /*  */ +.octicon-split:before { content: '\f0c6'} /*  */ +.octicon-squirrel:before { content: '\f0b2'} /*  */ +.octicon-star-add:before, +.octicon-star-delete:before, +.octicon-star:before { content: '\f02a'} /*  */ +.octicon-steps:before { content: '\f0c7'} /*  */ +.octicon-stop:before { content: '\f08f'} /*  */ +.octicon-repo-sync:before, +.octicon-sync:before { content: '\f087'} /*  */ +.octicon-tag-remove:before, +.octicon-tag-add:before, +.octicon-tag:before { content: '\f015'} /*  */ +.octicon-telescope:before { content: '\f088'} /*  */ +.octicon-terminal:before { content: '\f0c8'} /*  */ +.octicon-three-bars:before { content: '\f05e'} /*  */ +.octicon-tools:before { content: '\f031'} /*  */ +.octicon-trashcan:before { content: '\f0d0'} /*  */ +.octicon-triangle-down:before { content: '\f05b'} /*  */ +.octicon-triangle-left:before { content: '\f044'} /*  */ +.octicon-triangle-right:before { content: '\f05a'} /*  */ +.octicon-triangle-up:before { content: '\f0aa'} /*  */ +.octicon-unfold:before { content: '\f039'} /*  */ +.octicon-unmute:before { content: '\f0ba'} /*  */ +.octicon-versions:before { content: '\f064'} /*  */ +.octicon-remove-close:before, +.octicon-x:before { content: '\f081'} /*  */ +.octicon-zap:before { content: '\26A1'} /* ⚡ */ diff --git a/css/octicons.eot b/css/octicons.eot new file mode 100644 index 0000000000000000000000000000000000000000..22881a8b6c4342720d2d4318ef5887c8abbfc8a2 GIT binary patch literal 31440 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 + + + +(c) 2012-2014 GitHub + +When using the GitHub logos, be sure to follow the GitHub logo guidelines (https://github.com/logos) + +Font License: SIL OFL 1.1 (http://scripts.sil.org/OFL) +Applies to all font files + +Code License: MIT (http://choosealicense.com/licenses/mit/) +Applies to all other files + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fonts/octicons.ttf b/fonts/octicons.ttf new file mode 100644 index 0000000000000000000000000000000000000000..189ca2813d4920f3be1bd1a43b19a09740d1eb2c GIT binary patch literal 31272 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 F{||dHN2&k- literal 0 HcmV?d00001 diff --git a/fonts/octicons.woff b/fonts/octicons.woff new file mode 100644 index 0000000000000000000000000000000000000000..2b770e429f38d820c1916bb395f7e72ddafa60c5 GIT binary patch literal 17492 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 + @@ -129,6 +130,10 @@ require(HESK_PATH . 'nuMods_settings.inc.php');
    @@ -144,17 +149,17 @@ include(HESK_PATH . 'header.txt');
    diff --git a/inc/headerAdmin.inc.php b/inc/headerAdmin.inc.php index 1c462398..ae1a90f6 100644 --- a/inc/headerAdmin.inc.php +++ b/inc/headerAdmin.inc.php @@ -56,6 +56,7 @@ require(HESK_PATH . 'nuMods_settings.inc.php'); + @@ -130,4 +131,8 @@ require(HESK_PATH . 'nuMods_settings.inc.php'); diff --git a/nuMods_settings.inc.php b/nuMods_settings.inc.php index 855c65db..3fa94f97 100644 --- a/nuMods_settings.inc.php +++ b/nuMods_settings.inc.php @@ -16,5 +16,8 @@ $nuMods_settings['questionMarkColor'] = '#000000'; //-- Set this to 1 for right-to-left text. EXPERIMENTAL! $nuMods_settings['rtl'] = 0; +//-- Set this to 1 to show icons next to navigation menu items +$nuMods_settings['show_icons'] = 0; + /* DO NOT EDIT ANYTHING BELOW THIS LINE */ $nuMods_settings['version']='1.2.4'; From 666ffe7a777f02aea8b528f1cb64a0ed12e58d12 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 7 Sep 2014 23:28:51 -0400 Subject: [PATCH 034/208] Updated FontAwesome to 4.2.0 --- inc/header.inc.php | 2 +- inc/headerAdmin.inc.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/inc/header.inc.php b/inc/header.inc.php index 7d493fdc..32dbcf43 100644 --- a/inc/header.inc.php +++ b/inc/header.inc.php @@ -55,7 +55,7 @@ require(HESK_PATH . 'nuMods_settings.inc.php'); - + diff --git a/inc/headerAdmin.inc.php b/inc/headerAdmin.inc.php index ae1a90f6..6015b7e5 100644 --- a/inc/headerAdmin.inc.php +++ b/inc/headerAdmin.inc.php @@ -55,7 +55,7 @@ require(HESK_PATH . 'nuMods_settings.inc.php'); - + From 364b2fdd9156707e40494537ee11d5669121a116 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 7 Sep 2014 23:36:50 -0400 Subject: [PATCH 035/208] #42 Show font icons on the navigation menus if setting is enabled --- inc/header.inc.php | 12 ++++++------ inc/headerAdmin.inc.php | 2 +- inc/show_admin_nav.inc.php | 28 +++++++++++++++------------- 3 files changed, 22 insertions(+), 20 deletions(-) diff --git a/inc/header.inc.php b/inc/header.inc.php index 32dbcf43..e8d28894 100644 --- a/inc/header.inc.php +++ b/inc/header.inc.php @@ -130,7 +130,7 @@ require(HESK_PATH . 'nuMods_settings.inc.php'); diff --git a/inc/headerAdmin.inc.php b/inc/headerAdmin.inc.php index 6015b7e5..002d1ad5 100644 --- a/inc/headerAdmin.inc.php +++ b/inc/headerAdmin.inc.php @@ -131,7 +131,7 @@ require(HESK_PATH . 'nuMods_settings.inc.php'); From fa705816c5c240e4f7b1bd2237d3a3f83155f03f Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 7 Sep 2014 23:41:00 -0400 Subject: [PATCH 036/208] Only show login icon when icons are enabled --- admin/index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/index.php b/admin/index.php index f37414a2..4dcf0239 100644 --- a/admin/index.php +++ b/admin/index.php @@ -279,7 +279,7 @@ function print_login()
    -
    +
    ';} else { echo '
    ';}?>
    From 291b8fcf5bcbd9d5e367a1d033f01ff4e550351d Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 7 Sep 2014 23:41:13 -0400 Subject: [PATCH 037/208] Shouldn't push the attachments file out in releases. --- attachments/__latest.txt | 1 - 1 file changed, 1 deletion(-) delete mode 100644 attachments/__latest.txt diff --git a/attachments/__latest.txt b/attachments/__latest.txt deleted file mode 100644 index ec318b1a..00000000 --- a/attachments/__latest.txt +++ /dev/null @@ -1 +0,0 @@ -1410138724|2.5.5 \ No newline at end of file From cc055e3f1206cfc8cb363a2a522678c592854d64 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 7 Sep 2014 23:41:22 -0400 Subject: [PATCH 038/208] Updated version number --- README.md | 2 +- nuMods_settings.inc.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b8506378..dff9cd5c 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ [![Stories in Ready](https://badge.waffle.io/mkoch227/numods.png?label=ready&title=Ready)](https://waffle.io/mkoch227/numods) -

    NuMods v1.2.4

    +

    NuMods v1.3.0

    This branch contains all files modified from the base version of HESK to become NuMods, a set of modifications for HESK v2.x diff --git a/nuMods_settings.inc.php b/nuMods_settings.inc.php index 3fa94f97..09b5bb15 100644 --- a/nuMods_settings.inc.php +++ b/nuMods_settings.inc.php @@ -20,4 +20,4 @@ $nuMods_settings['rtl'] = 0; $nuMods_settings['show_icons'] = 0; /* DO NOT EDIT ANYTHING BELOW THIS LINE */ -$nuMods_settings['version']='1.2.4'; +$nuMods_settings['version']='1.3.0'; From 98a7633cb64d778310702344d75bbf41213bbf24 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Tue, 9 Sep 2014 22:12:13 -0400 Subject: [PATCH 039/208] Getting started on LDAP/Active Directory integration I still have no clue if any of this works; I'm just using a code snippet to get started on this. Still need to LDAP escape the user string (don't want them sending in *!) and test the whole thing. --- admin/index.php | 52 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 42 insertions(+), 10 deletions(-) diff --git a/admin/index.php b/admin/index.php index 4dcf0239..17584fe5 100644 --- a/admin/index.php +++ b/admin/index.php @@ -37,6 +37,7 @@ define('HESK_PATH','../'); /* Get all the required files and functions */ require(HESK_PATH . 'hesk_settings.inc.php'); +require(HESK_PATH . 'nuMods_settings.inc.php'); require(HESK_PATH . 'inc/common.inc.php'); require(HESK_PATH . 'inc/admin_functions.inc.php'); hesk_load_database_functions(); @@ -70,7 +71,7 @@ exit(); /*** START FUNCTIONS ***/ function do_login() { - global $hesk_settings, $hesklang; + global $hesk_settings, $hesklang, $nuMods_settings; $hesk_error_buffer = array(); @@ -176,25 +177,56 @@ function do_login() $_SESSION[$k]=$v; } - /* Check password */ - if (hesk_Pass2Hash($pass) != $_SESSION['pass']) + // Check if the user should be authenticated via Active Directory / LDAP + $usesLdap = $res['UsesLDAP']; + if ($usesLdap) { + //-- do AD-specific logic here. + $application_user = $nuMods_settings['ldap_application_user']; + $password = $nuMods_settings['ldap_application_password']; + + //-- Connect to LDAP server + $connectionIp = $nuMods_settings['ldap_server_ip']; + $port = $nuMods_settings['ldap_server_port']; + $connection = ldap_connect($connectionIp, $port); + if ($connection == false) { + die("Couldn't connect to LDAP server."); + } + + //-- Bind the application user to the connection + $bind = ldap_bind($connection, $application_user, $password); + if ($bind == false) { + die("Couldn't authenticate as the application user."); + } + + //-- Find the user's DN + //TODO LDAP escape the $user string! + $dnQuery = "(&(uid=" . $user . ")(objectClass=person))"; + $search_base = $nuMods_settings['ldap_search_base']; + $search_status = ldap_search( + $connection, $search_base, $dnQuery, array('dn') + ); + + } + + /* Check password */ + if (hesk_Pass2Hash($pass) != $_SESSION['pass']) { hesk_session_stop(); - $_SESSION['a_iserror'] = array('pass'); - hesk_process_messages($hesklang['wrong_pass'],'NOREDIRECT'); - print_login(); - exit(); - } + $_SESSION['a_iserror'] = array('pass'); + hesk_process_messages($hesklang['wrong_pass'],'NOREDIRECT'); + print_login(); + exit(); + } $pass_enc = hesk_Pass2Hash($_SESSION['pass'].strtolower($user).$_SESSION['pass']); /* Check if default password */ if ($_SESSION['pass'] == '499d74967b28a841c98bb4baaabaad699ff3c079') { - hesk_process_messages($hesklang['chdp'],'NOREDIRECT','NOTICE'); + hesk_process_messages($hesklang['chdp'],'NOREDIRECT','NOTICE'); } - unset($_SESSION['pass']); + unset($_SESSION['pass']); /* Login successful, clean brute force attempts */ hesk_cleanBfAttempts(); From 0e6bb7c2e4d9658551a6a78077374547067f2803 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Wed, 10 Sep 2014 18:42:09 -0400 Subject: [PATCH 040/208] Made some more progress on AD authentication --- admin/index.php | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/admin/index.php b/admin/index.php index 17584fe5..c3e01bf0 100644 --- a/admin/index.php +++ b/admin/index.php @@ -202,9 +202,36 @@ function do_login() //TODO LDAP escape the $user string! $dnQuery = "(&(uid=" . $user . ")(objectClass=person))"; $search_base = $nuMods_settings['ldap_search_base']; - $search_status = ldap_search( + $search = ldap_search( $connection, $search_base, $dnQuery, array('dn') ); + if ($search == false) { + die("Search failed."); + } + + $search_result = ldap_get_entries($connection, $search); + if ($search_result == false) { + die("Couldn't pull information from LDAP/AD server"); + } + $userdn = ''; + if ((int) @$search_result['count'] > 0) { + // Definitely pulled something, we don't check here + // for this example if it's more results than 1, + // although you should. + $userdn = $result[0]['dn']; + } + + if (trim((string) $userdn) == '') { + die("Empty DN. Something is wrong."); + } + + // Authenticate with the newly found DN and user-provided password + $auth_status = ldap_bind($connection, $userdn, $pass); + if ($auth_status === FALSE) { + //-- Login failed! + $_SESSION['a_iserror'] = array('pass'); + hesk_process_messages($hesklang['wrong_pass'],'NOREDIRECT'); + } } From 30b4c2a9080a5f25279f2a9c13eb8ddcde1fc640 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Wed, 10 Sep 2014 20:28:14 -0400 Subject: [PATCH 041/208] Revert "Made some more progress on AD authentication" This reverts commit 0e6bb7c2e4d9658551a6a78077374547067f2803. --- admin/index.php | 29 +---------------------------- 1 file changed, 1 insertion(+), 28 deletions(-) diff --git a/admin/index.php b/admin/index.php index c3e01bf0..17584fe5 100644 --- a/admin/index.php +++ b/admin/index.php @@ -202,36 +202,9 @@ function do_login() //TODO LDAP escape the $user string! $dnQuery = "(&(uid=" . $user . ")(objectClass=person))"; $search_base = $nuMods_settings['ldap_search_base']; - $search = ldap_search( + $search_status = ldap_search( $connection, $search_base, $dnQuery, array('dn') ); - if ($search == false) { - die("Search failed."); - } - - $search_result = ldap_get_entries($connection, $search); - if ($search_result == false) { - die("Couldn't pull information from LDAP/AD server"); - } - $userdn = ''; - if ((int) @$search_result['count'] > 0) { - // Definitely pulled something, we don't check here - // for this example if it's more results than 1, - // although you should. - $userdn = $result[0]['dn']; - } - - if (trim((string) $userdn) == '') { - die("Empty DN. Something is wrong."); - } - - // Authenticate with the newly found DN and user-provided password - $auth_status = ldap_bind($connection, $userdn, $pass); - if ($auth_status === FALSE) { - //-- Login failed! - $_SESSION['a_iserror'] = array('pass'); - hesk_process_messages($hesklang['wrong_pass'],'NOREDIRECT'); - } } From 84f6e91c0b47364ac7ec90c219140400e0360eb9 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Wed, 10 Sep 2014 20:28:22 -0400 Subject: [PATCH 042/208] Revert "Getting started on LDAP/Active Directory integration" This reverts commit 98a7633cb64d778310702344d75bbf41213bbf24. --- admin/index.php | 52 ++++++++++--------------------------------------- 1 file changed, 10 insertions(+), 42 deletions(-) diff --git a/admin/index.php b/admin/index.php index 17584fe5..4dcf0239 100644 --- a/admin/index.php +++ b/admin/index.php @@ -37,7 +37,6 @@ define('HESK_PATH','../'); /* Get all the required files and functions */ require(HESK_PATH . 'hesk_settings.inc.php'); -require(HESK_PATH . 'nuMods_settings.inc.php'); require(HESK_PATH . 'inc/common.inc.php'); require(HESK_PATH . 'inc/admin_functions.inc.php'); hesk_load_database_functions(); @@ -71,7 +70,7 @@ exit(); /*** START FUNCTIONS ***/ function do_login() { - global $hesk_settings, $hesklang, $nuMods_settings; + global $hesk_settings, $hesklang; $hesk_error_buffer = array(); @@ -177,56 +176,25 @@ function do_login() $_SESSION[$k]=$v; } - // Check if the user should be authenticated via Active Directory / LDAP - $usesLdap = $res['UsesLDAP']; - if ($usesLdap) { - //-- do AD-specific logic here. - $application_user = $nuMods_settings['ldap_application_user']; - $password = $nuMods_settings['ldap_application_password']; - - //-- Connect to LDAP server - $connectionIp = $nuMods_settings['ldap_server_ip']; - $port = $nuMods_settings['ldap_server_port']; - $connection = ldap_connect($connectionIp, $port); - if ($connection == false) { - die("Couldn't connect to LDAP server."); - } - - //-- Bind the application user to the connection - $bind = ldap_bind($connection, $application_user, $password); - if ($bind == false) { - die("Couldn't authenticate as the application user."); - } - - //-- Find the user's DN - //TODO LDAP escape the $user string! - $dnQuery = "(&(uid=" . $user . ")(objectClass=person))"; - $search_base = $nuMods_settings['ldap_search_base']; - $search_status = ldap_search( - $connection, $search_base, $dnQuery, array('dn') - ); - - } - - /* Check password */ - if (hesk_Pass2Hash($pass) != $_SESSION['pass']) + /* Check password */ + if (hesk_Pass2Hash($pass) != $_SESSION['pass']) { hesk_session_stop(); - $_SESSION['a_iserror'] = array('pass'); - hesk_process_messages($hesklang['wrong_pass'],'NOREDIRECT'); - print_login(); - exit(); - } + $_SESSION['a_iserror'] = array('pass'); + hesk_process_messages($hesklang['wrong_pass'],'NOREDIRECT'); + print_login(); + exit(); + } $pass_enc = hesk_Pass2Hash($_SESSION['pass'].strtolower($user).$_SESSION['pass']); /* Check if default password */ if ($_SESSION['pass'] == '499d74967b28a841c98bb4baaabaad699ff3c079') { - hesk_process_messages($hesklang['chdp'],'NOREDIRECT','NOTICE'); + hesk_process_messages($hesklang['chdp'],'NOREDIRECT','NOTICE'); } - unset($_SESSION['pass']); + unset($_SESSION['pass']); /* Login successful, clean brute force attempts */ hesk_cleanBfAttempts(); From 29aa70aab715d6d22737f912c8961220439e8b01 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Thu, 11 Sep 2014 21:52:44 -0400 Subject: [PATCH 043/208] custom0 isn't a valid custom field --- inc/ticket_list.inc.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inc/ticket_list.inc.php b/inc/ticket_list.inc.php index 8a15307c..a684e487 100644 --- a/inc/ticket_list.inc.php +++ b/inc/ticket_list.inc.php @@ -317,7 +317,7 @@ if ($total > 0) $ownerColumn = $ticket['owner'] != 0 ? $admins[$ticket['owner']] : '('.$hesklang['unas'].')'; $customFieldsHtml = ''; - for ($i = 0; $i <= 20; $i++) { + for ($i = 1; $i <= 20; $i++) { if ($hesk_settings['custom_fields']['custom'.$i]['use']) { $display = 'display: none'; if ((isset($_GET['sort']) && $_GET['sort'] == 'custom'.$i) || (isset($_GET['what']) && $_GET['what'] == 'custom'.$i)) { From df15806e42eeee773c300363d2d47c3e771b3575 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Thu, 11 Sep 2014 21:53:13 -0400 Subject: [PATCH 044/208] Closes #47: The panel now collapses to the correct size when there are 0 results. --- inc/ticket_list.inc.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/inc/ticket_list.inc.php b/inc/ticket_list.inc.php index a684e487..1bdd728d 100644 --- a/inc/ticket_list.inc.php +++ b/inc/ticket_list.inc.php @@ -479,8 +479,6 @@ EOC;
    - - 0 @@ -499,6 +497,8 @@ else echo ''; } +echo ' + '; function hesk_print_list_head() From 4983d2a6d7e05db03412b1f0ac3d66018e3ba25f Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Thu, 11 Sep 2014 22:00:26 -0400 Subject: [PATCH 045/208] Closes #48: Custom fields now follow proper styling on the print page --- print.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/print.php b/print.php index a10b4f24..c4508146 100644 --- a/print.php +++ b/print.php @@ -214,8 +214,8 @@ foreach ($hesk_settings['custom_fields'] as $k=>$v) $num_cols = 0; } ?> -
    ::
    - - - - - - - - - - - - - - - -
      - - -

    Verifying HESK installation

    - -

     

    - -

    Verifying your HESK installation...

    - - -

    OK: new files uploaded.

    - -

     

    - - -

    » Your HESK has been updated to version .

    -

    » To complete setup delete the /install folder from your server.

    - -

    Update failed: Cannot write to your hesk_settings.inc.php file.

    - -

    Please make sure the hesk_settings.inc.php file is writable by PHP then click the Try again button below.

    - -
    -

    -
    - -

    Missing files!

    - -

     

    - -

    Please upload all HESK patch files to your server.

    - -
    -

    -
    - - -

     

    -

     

    -

     

    - -
     
    -
    - - - - - - Install Hesk <?php echo HESK_NEW_VERSION; ?> - - - - - - - -
    - - - - - -
    - - - - - - -
    HESK installation script
    - -
    - - -

     
    Powered by Help Desk Software HESK - brought to you by Help Desk Software SysAid

    - - diff --git a/install/updateTo1-3-1.php b/install/updateTo1-3-1.php new file mode 100644 index 00000000..59d03bc8 --- /dev/null +++ b/install/updateTo1-3-1.php @@ -0,0 +1,11 @@ + + +

    Update complete!

    +

    Please delete the install folder for security reasons, and then proceed back to the Help Desk

    \ No newline at end of file From 97a4520d0be9af80495cef7454be55f2a2b344c0 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 14 Sep 2014 00:44:19 -0400 Subject: [PATCH 048/208] #35 removed irrelevant TODO --- admin/profile.php | 1 - 1 file changed, 1 deletion(-) diff --git a/admin/profile.php b/admin/profile.php index 8a75d308..af101562 100644 --- a/admin/profile.php +++ b/admin/profile.php @@ -426,7 +426,6 @@ function update_profile() { else { /* Update database */ - //TODO Add auto-refresh to the update SQL hesk_dbQuery( "UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."users` SET `name`='".hesk_dbEscape($_SESSION['new']['name'])."', From daaca6c63197ce1225b17bd74cd80dce2946fa01 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 14 Sep 2014 00:48:12 -0400 Subject: [PATCH 049/208] Fixed version # in language file --- language/en/text.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/language/en/text.php b/language/en/text.php index 495c6893..016e9118 100644 --- a/language/en/text.php +++ b/language/en/text.php @@ -21,7 +21,7 @@ $hesklang['_COLLATE']='utf8_unicode_ci'; // This is the email break line that will be used in email piping $hesklang['EMAIL_HR']='------ Reply above this line ------'; -// ADDED OR MODIFIED IN NuMods 1.2.5 +// ADDED OR MODIFIED IN NuMods 1.3.0 $hesklang['show_filters'] = 'Show Column Filters'; $hesklang['hide_filters'] = 'Hide Column Filters'; From 9f78ed41fd321412ddf43e1cdc2f0b9100ab4110 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 14 Sep 2014 00:55:28 -0400 Subject: [PATCH 050/208] #35 Ticket dashboard now shows autorefresh time --- inc/ticket_list.inc.php | 13 +++++++++++-- language/en/text.php | 3 +++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/inc/ticket_list.inc.php b/inc/ticket_list.inc.php index 1bdd728d..a47b3a20 100644 --- a/inc/ticket_list.inc.php +++ b/inc/ticket_list.inc.php @@ -114,8 +114,12 @@ if ($total > 0) $prev_page = ($page - 1 <= 0) ? 0 : $page - 1; $next_page = ($page + 1 > $pages) ? 0 : $page + 1; - - echo sprintf($hesklang['tickets_on_pages'],$total,$pages).'
    '; + $autorefreshInSeconds = $_SESSION['autorefresh']/1000; + $autorefresh = ''; + if ($autorefreshInSeconds > 0) { + $autorefresh = ' | '.$hesklang['autorefresh'].' '.$autorefreshInSeconds.' '.$hesklang['abbr']['second']; + } + echo sprintf($hesklang['tickets_on_pages'],$total,$pages).$autorefresh.'
    '; if ($pages > 1) { @@ -485,6 +489,11 @@ EOC; else { echo '
    '; + $autorefreshInSeconds = $_SESSION['autorefresh']/1000; + + if ($autorefreshInSeconds > 0) { + echo $hesklang['autorefresh'].' '.$autorefreshInSeconds.' '.$hesklang['abbr']['second']; + } if (isset($is_search) || $href == 'find_tickets.php') { diff --git a/language/en/text.php b/language/en/text.php index 016e9118..e1431e45 100644 --- a/language/en/text.php +++ b/language/en/text.php @@ -21,6 +21,9 @@ $hesklang['_COLLATE']='utf8_unicode_ci'; // This is the email break line that will be used in email piping $hesklang['EMAIL_HR']='------ Reply above this line ------'; +// ADDED OR MODIFIED IN NuMods 1.3.1 +$hesklang['autorefresh'] = 'Autorefresh:'; + // ADDED OR MODIFIED IN NuMods 1.3.0 $hesklang['show_filters'] = 'Show Column Filters'; $hesklang['hide_filters'] = 'Hide Column Filters'; From 93a72804f927b465c96eb66223a9324e7ce22e19 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 14 Sep 2014 00:57:41 -0400 Subject: [PATCH 051/208] #35 Refresh value must be 1000 or greater to prevent constant refreshes --- admin/profile.php | 2 +- inc/ticket_list.inc.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/admin/profile.php b/admin/profile.php index af101562..65b4b294 100644 --- a/admin/profile.php +++ b/admin/profile.php @@ -262,7 +262,7 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
    - Enter value in milliseconds, or 0 to disable. No fractional values. + Enter value in milliseconds, or 0 to disable. No fractional values, and value must be 1000 or greater.

    diff --git a/inc/ticket_list.inc.php b/inc/ticket_list.inc.php index a47b3a20..e065bdea 100644 --- a/inc/ticket_list.inc.php +++ b/inc/ticket_list.inc.php @@ -116,7 +116,7 @@ if ($total > 0) $next_page = ($page + 1 > $pages) ? 0 : $page + 1; $autorefreshInSeconds = $_SESSION['autorefresh']/1000; $autorefresh = ''; - if ($autorefreshInSeconds > 0) { + if ($autorefreshInSeconds > 999) { $autorefresh = ' | '.$hesklang['autorefresh'].' '.$autorefreshInSeconds.' '.$hesklang['abbr']['second']; } echo sprintf($hesklang['tickets_on_pages'],$total,$pages).$autorefresh.'
    '; @@ -491,7 +491,7 @@ else echo '
    '; $autorefreshInSeconds = $_SESSION['autorefresh']/1000; - if ($autorefreshInSeconds > 0) { + if ($autorefreshInSeconds > 999) { echo $hesklang['autorefresh'].' '.$autorefreshInSeconds.' '.$hesklang['abbr']['second']; } From 187db3635e82d9f7b59c9a0de81c1806f6148448 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 14 Sep 2014 01:14:54 -0400 Subject: [PATCH 052/208] Closes #35: Autorefresh now working on the ticket dashboards! --- admin/profile.php | 2 +- inc/ticket_list.inc.php | 21 +++++++++++++++++---- js/autorefresh.php | 7 +++++++ language/en/text.php | 1 + 4 files changed, 26 insertions(+), 5 deletions(-) create mode 100644 js/autorefresh.php diff --git a/admin/profile.php b/admin/profile.php index 65b4b294..aabac112 100644 --- a/admin/profile.php +++ b/admin/profile.php @@ -262,7 +262,7 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
    - Enter value in milliseconds, or 0 to disable. No fractional values, and value must be 1000 or greater. +

    diff --git a/inc/ticket_list.inc.php b/inc/ticket_list.inc.php index e065bdea..6078582b 100644 --- a/inc/ticket_list.inc.php +++ b/inc/ticket_list.inc.php @@ -31,7 +31,7 @@ * a license please visit the page below: * https://www.hesk.com/buy.php *******************************************************************************/ - +define('MINIMUM_REFRESH_THRESHOLD_IN_SECONDS', 1); /* Check if this is a valid include */ if (!defined('IN_SCRIPT')) {die('Invalid attempt');} @@ -116,9 +116,15 @@ if ($total > 0) $next_page = ($page + 1 > $pages) ? 0 : $page + 1; $autorefreshInSeconds = $_SESSION['autorefresh']/1000; $autorefresh = ''; - if ($autorefreshInSeconds > 999) { + if ($autorefreshInSeconds >= MINIMUM_REFRESH_THRESHOLD_IN_SECONDS) { $autorefresh = ' | '.$hesklang['autorefresh'].' '.$autorefreshInSeconds.' '.$hesklang['abbr']['second']; - } + ?> + + '; if ($pages > 1) @@ -491,8 +497,15 @@ else echo '
    '; $autorefreshInSeconds = $_SESSION['autorefresh']/1000; - if ($autorefreshInSeconds > 999) { + if ($autorefreshInSeconds >= MINIMUM_REFRESH_THRESHOLD_IN_SECONDS) { echo $hesklang['autorefresh'].' '.$autorefreshInSeconds.' '.$hesklang['abbr']['second']; + ?> + + MINIMUM_REFRESH_THRESHOLD_IN_MILLISECONDS) { ?> + (function(){ + setTimeout("location.reload(true);",); + })(); + \ No newline at end of file diff --git a/language/en/text.php b/language/en/text.php index e1431e45..fbf33f96 100644 --- a/language/en/text.php +++ b/language/en/text.php @@ -23,6 +23,7 @@ $hesklang['EMAIL_HR']='------ Reply above this line ------'; // ADDED OR MODIFIED IN NuMods 1.3.1 $hesklang['autorefresh'] = 'Autorefresh:'; +$hesklang['autorefresh_restrictions'] = 'Enter value in milliseconds. Value must be greater than 1000 to use this feature. No fractional values.'; // ADDED OR MODIFIED IN NuMods 1.3.0 $hesklang['show_filters'] = 'Show Column Filters'; From bdf2460755a5bd73666c6e05c1da1fae77283f61 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 14 Sep 2014 01:36:13 -0400 Subject: [PATCH 053/208] Closes #34: Very basic maintenance mode up and running --- inc/header.inc.php | 5 +++++ maintenance.php | 24 ++++++++++++++++++++++++ nuMods_settings.inc.php | 3 +++ 3 files changed, 32 insertions(+) create mode 100644 maintenance.php diff --git a/inc/header.inc.php b/inc/header.inc.php index e8d28894..0f76fa02 100644 --- a/inc/header.inc.php +++ b/inc/header.inc.php @@ -35,6 +35,10 @@ /* Check if this is a valid include */ if (!defined('IN_SCRIPT')) {die('Invalid attempt');} require(HESK_PATH . 'nuMods_settings.inc.php'); +// Check to see if we're in maintenance mode before sending anything to the DOM +if ($nuMods_settings['maintenance_mode'] && !defined('ON_MAINTENANCE_PAGE')) { + header('Location: '.HESK_PATH.'maintenance.php'); +} ?> @@ -62,6 +66,7 @@ require(HESK_PATH . 'nuMods_settings.inc.php'); +
    +
    +
    +

    The helpdesk is currently undergoing maintenance. Please come back later.

    +
    +
    + \ No newline at end of file diff --git a/nuMods_settings.inc.php b/nuMods_settings.inc.php index 09b5bb15..b30b23cf 100644 --- a/nuMods_settings.inc.php +++ b/nuMods_settings.inc.php @@ -19,5 +19,8 @@ $nuMods_settings['rtl'] = 0; //-- Set this to 1 to show icons next to navigation menu items $nuMods_settings['show_icons'] = 0; +//-- Set this to 1 to enable maintenance mode +$nuMods_settings['maintenance_mode'] = 0; + /* DO NOT EDIT ANYTHING BELOW THIS LINE */ $nuMods_settings['version']='1.3.0'; From b5361d683a09b201095ea015a71a68bb214e8d14 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 14 Sep 2014 01:40:58 -0400 Subject: [PATCH 054/208] Don't show the maintenance page when on the login screen --- admin/index.php | 1 + inc/header.inc.php | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/admin/index.php b/admin/index.php index 4dcf0239..a4031e58 100644 --- a/admin/index.php +++ b/admin/index.php @@ -34,6 +34,7 @@ define('IN_SCRIPT',1); define('HESK_PATH','../'); +define('ON_LOGIN_PAGE',1); /* Get all the required files and functions */ require(HESK_PATH . 'hesk_settings.inc.php'); diff --git a/inc/header.inc.php b/inc/header.inc.php index 0f76fa02..56edd27f 100644 --- a/inc/header.inc.php +++ b/inc/header.inc.php @@ -36,7 +36,7 @@ if (!defined('IN_SCRIPT')) {die('Invalid attempt');} require(HESK_PATH . 'nuMods_settings.inc.php'); // Check to see if we're in maintenance mode before sending anything to the DOM -if ($nuMods_settings['maintenance_mode'] && !defined('ON_MAINTENANCE_PAGE')) { +if ($nuMods_settings['maintenance_mode'] && !defined('ON_MAINTENANCE_PAGE') && !defined('ON_LOGIN_PAGE')) { header('Location: '.HESK_PATH.'maintenance.php'); } ?> From e357e62e0c33254d298c4288f70e953affbfdb4a Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Mon, 15 Sep 2014 22:20:24 -0400 Subject: [PATCH 055/208] #49 Getting started on the NuMods settings page --- admin/admin_settings.php | 61 ++++++++++++++++++++++++++++++- install/install_functions.inc.php | 2 +- language/en/text.php | 3 ++ 3 files changed, 64 insertions(+), 2 deletions(-) diff --git a/admin/admin_settings.php b/admin/admin_settings.php index 8997291e..363991b7 100644 --- a/admin/admin_settings.php +++ b/admin/admin_settings.php @@ -471,7 +471,15 @@ if ( defined('HESK_DEMO') )
  • -
  • + @@ -1773,6 +1781,57 @@ if ( defined('HESK_DEMO') )
    + +
    +
    +
    +
    + +
    +
    + +
    +
    +
    +
    + +
    +
    + +
    +
    +
    +
    + +
    +
    + +
    +
    +
    +
    +
    diff --git a/install/install_functions.inc.php b/install/install_functions.inc.php index 35a73f73..3859f666 100644 --- a/install/install_functions.inc.php +++ b/install/install_functions.inc.php @@ -37,7 +37,7 @@ if (!defined('IN_SCRIPT')) {die('Invalid attempt');} // We will be installing this HESK version: define('HESK_NEW_VERSION','2.5.5'); -define('NUMODS_NEW_VERSION','1.3.1'); +define('NUMODS_NEW_VERSION','1.4.0'); // Other required files and settings define('INSTALL',1); diff --git a/language/en/text.php b/language/en/text.php index fbf33f96..a474af84 100644 --- a/language/en/text.php +++ b/language/en/text.php @@ -21,6 +21,9 @@ $hesklang['_COLLATE']='utf8_unicode_ci'; // This is the email break line that will be used in email piping $hesklang['EMAIL_HR']='------ Reply above this line ------'; +// ADDED OR MODIFIED IN NuMods 1.4.0 +$hesklang['numods'] = 'NuMods'; + // ADDED OR MODIFIED IN NuMods 1.3.1 $hesklang['autorefresh'] = 'Autorefresh:'; $hesklang['autorefresh_restrictions'] = 'Enter value in milliseconds. Value must be greater than 1000 to use this feature. No fractional values.'; From 77e0b0172592aa67b49ef3da0c9deb7b0bce9a9c Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 21 Sep 2014 01:00:54 -0400 Subject: [PATCH 056/208] #49 NuMods settings can now be changed via the Settings page --- admin/admin_settings.php | 118 ++++++++++++++++++++++++++++++++-- admin/admin_settings_save.php | 51 +++++++++++++++ language/en/text.php | 16 +++++ 3 files changed, 179 insertions(+), 6 deletions(-) diff --git a/admin/admin_settings.php b/admin/admin_settings.php index 363991b7..ef1ec8d2 100644 --- a/admin/admin_settings.php +++ b/admin/admin_settings.php @@ -478,6 +478,7 @@ if ( defined('HESK_DEMO') ) @@ -1787,7 +1788,7 @@ if ( defined('HESK_DEMO') )
    +
    + +
    +
    +
    +
    +
    +
    + +
    + +
    +
    +
    +
    +
    + +
    + +
    +
    +
    +
    +
    +
    +
    + +
    + +
    +
    +
    +
    +
    + +
    + +
    +
    +
    +
    +
    +
    +
    + +
    + +
    +
    +
    +
    +
    + +
    + +
    +
    +
    +
    +
    +
    +
    + +
    + +
    +
    +
    +
    +
    + +
    + +
    +
    +
    +
    +
    +
    +
    + +
    + +
    +
    +
    +
    +
    + +
    + +
    +
    +
    +
    +
    +
    +
    + +
    + +
    +
    +
    +
    diff --git a/admin/admin_settings_save.php b/admin/admin_settings_save.php index 2411420f..fc9aa288 100644 --- a/admin/admin_settings_save.php +++ b/admin/admin_settings_save.php @@ -37,6 +37,7 @@ define('HESK_PATH','../'); /* Get all the required files and functions */ require(HESK_PATH . 'hesk_settings.inc.php'); +require(HESK_PATH . 'nuMods_settings.inc.php'); require(HESK_PATH . 'inc/common.inc.php'); require(HESK_PATH . 'inc/admin_functions.inc.php'); require(HESK_PATH . 'inc/email_functions.inc.php'); @@ -498,6 +499,56 @@ $stmt->execute(); $set['hesk_version'] = $hesk_settings['hesk_version']; +// Save the nuMods_settings.inc.php file +$set['nuMods_version'] = $nuMods_settings['version']; +$set['rtl'] = empty($_POST['rtl']) ? 0 : 1; +$set['show-icons'] = empty($_POST['show-icons']) ? 0 : 1; +$set['maintenance-mode'] = empty($_POST['maintenance-mode']) ? 0 : 1; +$set['navbarBackgroundColor'] = hesk_input(hesk_POST('navbarBackgroundColor')); +$set['navbarBrandColor'] = hesk_input(hesk_POST('navbarBrandColor')); +$set['navbarBrandHoverColor'] = hesk_input(hesk_POST('navbarBrandHoverColor')); +$set['navbarItemTextColor'] = hesk_input(hesk_POST('navbarItemTextColor')); +$set['navbarItemTextHoverColor'] = hesk_input(hesk_POST('navbarItemTextHoverColor')); +$set['navbarItemTextSelectedColor'] = hesk_input(hesk_POST('navbarItemTextSelectedColor')); +$set['navbarItemSelectedBackgroundColor'] = hesk_input(hesk_POST('navbarItemSelectedBackgroundColor')); +$set['dropdownItemTextColor'] = hesk_input(hesk_POST('dropdownItemTextColor')); +$set['dropdownItemTextHoverColor'] = hesk_input(hesk_POST('dropdownItemTextHoverColor')); +$set['questionMarkColor'] = hesk_input(hesk_POST('questionMarkColor')); +$set['dropdownItemTextHoverBackgroundColor'] = hesk_input(hesk_POST('dropdownItemTextHoverBackgroundColor')); +$nuMods_file_content='nuMods_settings.inc.php for writing. Please CHMOD this file to 666 (rw-rw-rw-)'; // ADDED OR MODIFIED IN NuMods 1.3.1 $hesklang['autorefresh'] = 'Autorefresh:'; From a277ce106012287bf5f7b6f492c4a8963597b00e Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 21 Sep 2014 01:22:27 -0400 Subject: [PATCH 057/208] Use the settingsquestionmark class for all question marks --- admin/manage_canned.php | 2 +- admin/manage_categories.php | 2 +- admin/manage_knowledgebase.php | 2 +- admin/manage_users.php | 2 +- css/hesk_newStyle.php | 3 --- 5 files changed, 4 insertions(+), 7 deletions(-) diff --git a/admin/manage_canned.php b/admin/manage_canned.php index 752d959b..f3a61a18 100644 --- a/admin/manage_canned.php +++ b/admin/manage_canned.php @@ -225,7 +225,7 @@ myField.value += myValue; /* This will handle error, success and notice messages */ hesk_handle_messages(); ?> -

    +

    diff --git a/admin/manage_categories.php b/admin/manage_categories.php index 0c119d0d..d3a596ce 100644 --- a/admin/manage_categories.php +++ b/admin/manage_categories.php @@ -174,7 +174,7 @@ else {return false;} /* This will handle error, success and notice messages */ hesk_handle_messages(); ?> -

    +

    diff --git a/admin/manage_knowledgebase.php b/admin/manage_knowledgebase.php index e2c18228..2787301a 100644 --- a/admin/manage_knowledgebase.php +++ b/admin/manage_knowledgebase.php @@ -263,7 +263,7 @@ if (!isset($_SESSION['hide']['treemenu'])) { ?>
    -

    +

    diff --git a/admin/manage_users.php b/admin/manage_users.php index 0f1fff83..e8559d74 100644 --- a/admin/manage_users.php +++ b/admin/manage_users.php @@ -315,7 +315,7 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php'); hesk_handle_messages(); ?> -

    +

    diff --git a/css/hesk_newStyle.php b/css/hesk_newStyle.php index 734aa36f..c7b2ac21 100644 --- a/css/hesk_newStyle.php +++ b/css/hesk_newStyle.php @@ -123,9 +123,6 @@ color: ; font-size: 14px; } -.settingsquestionmark:hover { - text-decoration: underline; -} .h3questionmark { color: ; font-size: 14px; From e86e61065ab8403fa2a1cecd9596773b87a5ea1f Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 21 Sep 2014 01:28:54 -0400 Subject: [PATCH 058/208] Closes #49: Add help text to all NuMods settings. --- admin/admin_settings.php | 89 +++++++++++++++++++++++++++++----------- language/en/text.php | 14 +++++++ nuMods_settings.inc.php | 2 +- 3 files changed, 81 insertions(+), 24 deletions(-) diff --git a/admin/admin_settings.php b/admin/admin_settings.php index ef1ec8d2..87ff3ae6 100644 --- a/admin/admin_settings.php +++ b/admin/admin_settings.php @@ -459,7 +459,7 @@ if ( defined('HESK_DEMO') ) //--> -

    +

    @@ -1789,9 +1789,9 @@ if ( defined('HESK_DEMO') )
    @@ -1804,9 +1804,9 @@ if ( defined('HESK_DEMO') )
    @@ -1817,11 +1817,10 @@ if ( defined('HESK_DEMO') )
    -
    + + + + + + + + + fetch_assoc()) { + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + } + + ?> + + + + + + + +
    Delete (!) From(!) To
    (!)Add New + + + +
    +
    From 7b3bc087b1f8a948f228bc8bede16ea04c7e7828 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Wed, 24 Sep 2014 22:02:24 -0400 Subject: [PATCH 062/208] The UI for IP/Email bans is ready to go --- admin/admin_settings.php | 54 +++++++++++++++++++++++++++++++-------- install/updateTo1-4-0.php | 2 +- language/en/text.php | 4 +++ 3 files changed, 48 insertions(+), 12 deletions(-) diff --git a/admin/admin_settings.php b/admin/admin_settings.php index 8fea1baa..879f19b1 100644 --- a/admin/admin_settings.php +++ b/admin/admin_settings.php @@ -479,7 +479,7 @@ if ( defined('HESK_DEMO') )
  • -
  • (!) IP / Email Bans
  • +
  • @@ -2157,16 +2157,16 @@ if ( defined('HESK_DEMO') )
    -
    -
    (!) IP Bans
    +
    +
    - - - + + + @@ -2175,25 +2175,57 @@ if ( defined('HESK_DEMO') ) while ($row = $ipRs->fetch_assoc()) { echo ''; echo ''; - echo ''; - echo ''; + echo ''; + echo ''; echo ''; } ?> - +
    Delete (!) From(!) To
    (!)Add New - + - +
    +
    +
    +
    +
    + + + + + + + + + fetch_assoc()) { + echo ''; + echo ''; + echo ''; + echo ''; + } + ?> + + + + + + + +
    + +
    +
    diff --git a/install/updateTo1-4-0.php b/install/updateTo1-4-0.php index 6155b631..e2d4dddd 100644 --- a/install/updateTo1-4-0.php +++ b/install/updateTo1-4-0.php @@ -8,7 +8,7 @@ hesk_dbQuery("CREATE TABLE `".$hesk_settings['db_pfix']."denied_ips` ( `ID` INT NOT NULL PRIMARY KEY AUTO_INCREMENT, `RangeStart` VARCHAR(100) NOT NULL, `RangeEnd` VARCHAR(100) NOT NULL)"); -hesk_dbQuery("CREATE TABLE `".$hesk_settings['db_pfix']."denied_emails` (Email VARCHAR(100) NOT NULL PRIMARY KEY);"); +hesk_dbQuery("CREATE TABLE `".$hesk_settings['db_pfix']."denied_emails` (ID INT NOT NULL PRIMARY KEY AUTO_INCREMENT, Email VARCHAR(100) NOT NULL PRIMARY KEY);"); ?>

    Update complete!

    diff --git a/language/en/text.php b/language/en/text.php index 51bfaacd..116dcfb8 100644 --- a/language/en/text.php +++ b/language/en/text.php @@ -53,6 +53,10 @@ $hesklang['showIconsHelp'] = 'Check this box to show icons next to navigation ba $hesklang['maintenanceMode'] = 'Maintenance Mode'; $hesklang['maintenanceModeHelp'] = 'Check this box to put the Help Desk in maintenance mode. Staff can still log into the backend, but the front end will be inaccessible.'; $hesklang['err_nuMods_settings'] = 'Can\'t open file nuMods_settings.inc.php for writing. Please CHMOD this file to 666 (rw-rw-rw-)'; +$hesklang['ip_to'] = 'To'; +$hesklang['ip_bans'] = 'IP Bans'; +$hesklang['email_bans'] = 'Email Bans'; +$hesklang['ip_email_bans'] = 'IP / Email Bans'; // ADDED OR MODIFIED IN NuMods 1.3.1 $hesklang['autorefresh'] = 'Autorefresh:'; From 26887979e171f97d7c0c9c605ac12e5ce7862f22 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Wed, 24 Sep 2014 23:48:00 -0400 Subject: [PATCH 063/208] #29 Now IP ranges and emails can be added to the banned tables thru the settings page --- admin/admin_settings.php | 48 +++++++++++++++++------------------ admin/admin_settings_save.php | 32 +++++++++++++++++++++++ 2 files changed, 56 insertions(+), 24 deletions(-) diff --git a/admin/admin_settings.php b/admin/admin_settings.php index 879f19b1..8f3a2642 100644 --- a/admin/admin_settings.php +++ b/admin/admin_settings.php @@ -2156,7 +2156,7 @@ if ( defined('HESK_DEMO') )
    - +
    @@ -2174,9 +2174,9 @@ if ( defined('HESK_DEMO') ) $ipRs= hesk_dbQuery('SELECT * FROM `'.$hesk_settings['db_pfix'].'denied_ips`'); while ($row = $ipRs->fetch_assoc()) { echo '
    - - - - + + + + - fetch_assoc()) { - echo ''; - echo ''; - echo ''; - echo ''; - } - ?> + fetch_assoc()) { + echo ''; + echo ''; + echo ''; + echo ''; + } + ?> - - - - - + + + + +
    - -
    + +
    diff --git a/admin/admin_settings_save.php b/admin/admin_settings_save.php index fc9aa288..faa6d158 100644 --- a/admin/admin_settings_save.php +++ b/admin/admin_settings_save.php @@ -497,6 +497,38 @@ $stmt = hesk_dbConnect()->prepare($updateQuery); $stmt->bind_param('i', $_POST['lockedTicketStatus']); $stmt->execute(); +//-- IP Bans +$ipBanSql = hesk_dbQuery('SELECT * FROM `'.$hesk_settings['db_pfix'].'denied_ips`'); +while ($row = $ipBanSql->fetch_assoc()) { + if (isset($_POST['ipDelete'][$row['ID']])) { + hesk_dbQuery('DELETE FROM `'.hesk_dbEscape($hesk_settings['db_pfix']).'denied_ips` WHERE ID = '.hesk_dbEscape($row['ID'])); + } else { + hesk_dbQuery('UPDATE `'.hesk_dbEscape($hesk_settings['db_pfix']).'denied_ips` + SET `RangeStart` = \''.hesk_dbEscape($_POST['ipFrom'][$row['ID']]).'\', + `RangeEnd` = \''.hesk_dbEscape($_POST['ipTo'][$row['ID']]).'\' + WHERE ID = '.hesk_dbEscape($row['ID'])); + } +} +if (!empty($_POST['addIpFrom']) && !empty($_POST['addIpTo'])) { + hesk_dbQuery('INSERT INTO `'.hesk_dbEscape($hesk_settings['db_pfix']).'denied_ips` (`RangeStart`, `RangeEnd`) + VALUES (\''.hesk_dbEscape($_POST['addIpFrom']).'\', \''.hesk_dbEscape($_POST['addIpTo']).'\')'); +} + +//-- Email Bans +$emailBanSql = hesk_dbQuery('SELECT * FROM `'.hesk_dbEscape($hesk_settings['db_pfix']).'denied_emails`'); +while ($row = $emailBanSql->fetch_assoc()) { + if (isset($_POST['emailDelete'][$row['ID']])) { + hesk_dbQuery('DELETE FROM `'.hesk_dbEscape($hesk_settings['db_pfix']).'denied_emails` WHERE ID = '.hesk_dbEscape($row['ID'])); + } else { + hesk_dbQuery('UPDATE `'.hesk_dbEscape($hesk_settings['db_pfix']).'denied_emails` + SET Email = \''.hesk_dbEscape($_POST['email'][$row['ID']]).'\' + WHERE ID = '.hesk_dbEscape($row['ID'])); + } +} +if (!empty($_POST['addEmail'])) { + hesk_dbQuery('INSERT INTO `'.hesk_dbEscape($hesk_settings['db_pfix']).'denied_emails` (Email) VALUES (\''.hesk_dbEscape($_POST['addEmail']).'\')'); +} + $set['hesk_version'] = $hesk_settings['hesk_version']; // Save the nuMods_settings.inc.php file From 6c25a381348b40420ec28fffd4425f0ec27ae7cf Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Thu, 25 Sep 2014 21:11:20 -0400 Subject: [PATCH 064/208] #29 Use ip2long / long2ip to convert IP addresses to easily compare --- admin/admin_settings.php | 4 ++-- admin/admin_settings_save.php | 10 +++++++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/admin/admin_settings.php b/admin/admin_settings.php index 8f3a2642..293f6b36 100644 --- a/admin/admin_settings.php +++ b/admin/admin_settings.php @@ -2175,8 +2175,8 @@ if ( defined('HESK_DEMO') ) while ($row = $ipRs->fetch_assoc()) { echo ''; echo ''; - echo ''; - echo ''; + echo ''; + echo ''; echo ''; } diff --git a/admin/admin_settings_save.php b/admin/admin_settings_save.php index faa6d158..50cb4680 100644 --- a/admin/admin_settings_save.php +++ b/admin/admin_settings_save.php @@ -503,15 +503,19 @@ while ($row = $ipBanSql->fetch_assoc()) { if (isset($_POST['ipDelete'][$row['ID']])) { hesk_dbQuery('DELETE FROM `'.hesk_dbEscape($hesk_settings['db_pfix']).'denied_ips` WHERE ID = '.hesk_dbEscape($row['ID'])); } else { + $ipAddressFrom = ip2long($_POST['ipFrom'][$row['ID']]); + $ipAddressTo = ip2long($_POST['ipTo'][$row['ID']]); hesk_dbQuery('UPDATE `'.hesk_dbEscape($hesk_settings['db_pfix']).'denied_ips` - SET `RangeStart` = \''.hesk_dbEscape($_POST['ipFrom'][$row['ID']]).'\', - `RangeEnd` = \''.hesk_dbEscape($_POST['ipTo'][$row['ID']]).'\' + SET `RangeStart` = \''.hesk_dbEscape($ipAddressFrom).'\', + `RangeEnd` = \''.hesk_dbEscape($ipAddressTo).'\' WHERE ID = '.hesk_dbEscape($row['ID'])); } } if (!empty($_POST['addIpFrom']) && !empty($_POST['addIpTo'])) { + $ipAddressFrom = ip2long($_POST['addIpFrom']); + $ipAddressTo = ip2long($_POST['addIpTo']); hesk_dbQuery('INSERT INTO `'.hesk_dbEscape($hesk_settings['db_pfix']).'denied_ips` (`RangeStart`, `RangeEnd`) - VALUES (\''.hesk_dbEscape($_POST['addIpFrom']).'\', \''.hesk_dbEscape($_POST['addIpTo']).'\')'); + VALUES (\''.hesk_dbEscape($ipAddressFrom).'\', \''.hesk_dbEscape($ipAddressTo).'\')'); } //-- Email Bans From 7ede557b64438860f0343f1b298e71ccc67cdf21 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Thu, 25 Sep 2014 21:11:53 -0400 Subject: [PATCH 065/208] #29 IP / Email bans now are used on the submit ticket page. Still need to do POP3 fetching / piping. --- language/en/text.php | 2 ++ submit_ticket.php | 13 +++++++++++++ 2 files changed, 15 insertions(+) diff --git a/language/en/text.php b/language/en/text.php index 116dcfb8..52378770 100644 --- a/language/en/text.php +++ b/language/en/text.php @@ -57,6 +57,8 @@ $hesklang['ip_to'] = 'To'; $hesklang['ip_bans'] = 'IP Bans'; $hesklang['email_bans'] = 'Email Bans'; $hesklang['ip_email_bans'] = 'IP / Email Bans'; +$hesklang['ip_banned'] = 'Your IP has been banned by the help desk. You will be unable to submit a ticket until your IP ban has been removed.'; +$hesklang['email_banned'] = 'The email address you have entered has been banned by the help desk. You will be unable to submit a ticket until your email ban has been removed.'; // ADDED OR MODIFIED IN NuMods 1.3.1 $hesklang['autorefresh'] = 'Autorefresh:'; diff --git a/submit_ticket.php b/submit_ticket.php index 7df76219..f2e436eb 100644 --- a/submit_ticket.php +++ b/submit_ticket.php @@ -78,6 +78,19 @@ hesk_dbConnect(); $hesk_error_buffer = array(); +// Check to see if the user's IP address or email they submitted is banned. +$ipAddress = ip2long($_SERVER['REMOTE_ADDR']); +$ipSql = hesk_dbQuery('SELECT * FROM `'.hesk_dbEscape($hesk_settings['db_pfix']).'denied_ips` WHERE `RangeStart` <= \''.hesk_dbEscape($ipAddress) + .'\' AND `RangeEnd` >= \''.hesk_dbEscape($ipAddress).'\''); +if ($ipSql->num_rows > 0) { + $hesk_error_buffer['ip_ban'] = $hesklang['ip_banned']; +} + +$emailSql = hesk_dbQuery('SELECT * FROM `'.hesk_dbEscape($hesk_settings['db_pfix']).'denied_emails` WHERE Email = \''.hesk_dbEscape(hesk_POST('email')).'\''); +if ($emailSql->num_rows > 0) { + $hesk_error_buffer['email_ban'] = $hesklang['email_banned']; +} + // Check anti-SPAM question if ($hesk_settings['question_use']) { From e045921e9fab71cb53d5851d4dea617e1b643e46 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Thu, 25 Sep 2014 21:32:33 -0400 Subject: [PATCH 066/208] #29 Check the banned emails list for piped emails We can't check IPs since they can't always be pulled from the email. --- .gitignore | 1 - inc/pipe_functions.inc.php | 505 +++++++++++++++++++++++++++++++++++++ 2 files changed, 505 insertions(+), 1 deletion(-) create mode 100755 inc/pipe_functions.inc.php diff --git a/.gitignore b/.gitignore index 3c8db864..aff7c4f2 100644 --- a/.gitignore +++ b/.gitignore @@ -183,7 +183,6 @@ inc/mail/sasl/ntlm_sasl_client.php inc/mail/sasl/plain_sasl_client.php inc/mail/sasl/sasl.php inc/mail/smtp.php -inc/pipe_functions.inc.php inc/posting_functions.inc.php inc/prepare_ticket_export.inc.php inc/print_group.inc.php diff --git a/inc/pipe_functions.inc.php b/inc/pipe_functions.inc.php new file mode 100755 index 00000000..cf4e7016 --- /dev/null +++ b/inc/pipe_functions.inc.php @@ -0,0 +1,505 @@ +num_rows > 0) { + return hesk_cleanExit(); + } + + // Process "From:" name, convert to UTF-8, set to "[Customer]" if not set + $tmpvar['name'] = isset($results['from'][0]['name']) ? $results['from'][0]['name'] : $hesklang['pde']; + if ( ! empty($results['from'][0]['encoding']) ) + { + $tmpvar['name'] = hesk_encodeUTF8($tmpvar['name'], $results['from'][0]['encoding']); + } + $tmpvar['name'] = hesk_input($tmpvar['name'],'','',1,50) or $tmpvar['name'] = $hesklang['pde']; + + // Process "To:" email (not yet implemented, for future use) + // $tmpvar['to_email'] = hesk_validateEmail($results['to'][0]['address'],'ERR',0); + + // Process email subject, convert to UTF-8, set to "[Piped email]" if none set + $tmpvar['subject'] = isset($results['subject']) ? $results['subject'] : $hesklang['pem']; + if ( ! empty($results['subject_encoding']) ) + { + $tmpvar['subject'] = hesk_encodeUTF8($tmpvar['subject'], $results['subject_encoding']); + } + $tmpvar['subject'] = hesk_input($tmpvar['subject'],'','',1,70) or $tmpvar['subject'] = $hesklang['pem']; + + // Process email message, convert to UTF-8 + $tmpvar['message'] = isset($results['message']) ? $results['message'] : ''; + if ( ! empty($results['encoding']) ) + { + $tmpvar['message'] = hesk_encodeUTF8($tmpvar['message'], $results['encoding']); + } + $tmpvar['message'] = hesk_input($tmpvar['message'],'','',1); + + // Message missing? We require it! + if ( ! $tmpvar['message']) + { + return hesk_cleanExit(); + } + + // Strip quoted reply from email + $tmpvar['message'] = hesk_stripQuotedText($tmpvar['message']); + + // Convert URLs to links, change newlines to
    + $tmpvar['message'] = hesk_makeURL($tmpvar['message']); + $tmpvar['message'] = nl2br($tmpvar['message']); + + # For debugging purposes + # die( bin2hex($tmpvar['message']) ); + # die($tmpvar['message']); + + // Try to detect "delivery failed" and "noreply" emails - ignore if detected + if ( hesk_isReturnedEmail($tmpvar) ) + { + return hesk_cleanExit(); + } + + // Check for email loops + if ( hesk_isEmailLoop($tmpvar['email'], md5($tmpvar['message']) ) ) + { + return hesk_cleanExit(); + } + + // OK, everything seems OK. Now determine if this is a reply to a ticket or a new ticket + if ( preg_match('/\[#([A-Z0-9]{3}\-[A-Z0-9]{3}\-[A-Z0-9]{4})\]/', str_replace(' ', '', $tmpvar['subject']), $matches) ) + { + // We found a possible tracking ID + $tmpvar['trackid'] = $matches[1]; + + // Does it match one in the database? + $res = hesk_dbQuery("SELECT * FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` WHERE `trackid`='".hesk_dbEscape($tmpvar['trackid'])."' LIMIT 1"); + if (hesk_dbNumRows($res)) + { + $ticket = hesk_dbFetchAssoc($res); + + // Do email addresses match? + if ( strpos( strtolower($ticket['email']), strtolower($tmpvar['email']) ) === false ) + { + $tmpvar['trackid'] = ''; + } + + // Is this ticket locked? Force create a new one if it is + if ($ticket['locked']) + { + $tmpvar['trackid'] = ''; + } + } + else + { + $tmpvar['trackid'] = ''; + } + } + + // If tracking ID is empty, generate a new one + if ( empty($tmpvar['trackid']) ) + { + $tmpvar['trackid'] = hesk_createID(); + $is_reply = 0; + } + else + { + $is_reply = 1; + } + + // Process attachments + $tmpvar['attachmment_notices'] = ''; + $tmpvar['attachments'] = ''; + $num = 0; + if ($hesk_settings['attachments']['use'] && isset($results['attachments'][0])) + { + #print_r($results['attachments']); + + foreach ($results['attachments'] as $k => $v) + { + + // Clean attachment names + $myatt['real_name'] = hesk_cleanFileName($v['orig_name']); + + // Check number of attachments, delete any over max number + if ($num >= $hesk_settings['attachments']['max_number']) + { + $tmpvar['attachmment_notices'] .= sprintf($hesklang['attnum'], $myatt['real_name']) . "\n"; + continue; + } + + // Check file extension + $ext = strtolower(strrchr($myatt['real_name'], ".")); + if (!in_array($ext,$hesk_settings['attachments']['allowed_types'])) + { + $tmpvar['attachmment_notices'] .= sprintf($hesklang['atttyp'], $myatt['real_name']) . "\n"; + continue; + } + + // Check file size + $myatt['size'] = $v['size']; + if ($myatt['size'] > ($hesk_settings['attachments']['max_size'])) + { + $tmpvar['attachmment_notices'] .= sprintf($hesklang['attsiz'], $myatt['real_name']) . "\n"; + continue; + } + + // Generate a random file name + $useChars='AEUYBDGHJLMNPQRSTVWXZ123456789'; + $tmp = $useChars{mt_rand(0,29)}; + for($j=1;$j<10;$j++) + { + $tmp .= $useChars{mt_rand(0,29)}; + } + $myatt['saved_name'] = substr($tmpvar['trackid'] . '_' . md5($tmp . $myatt['real_name']), 0, 200) . $ext; + + // Rename the temporary file + rename($v['stored_name'],HESK_PATH.$hesk_settings['attach_dir'].'/'.$myatt['saved_name']); + + // Insert into database + hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."attachments` (`ticket_id`,`saved_name`,`real_name`,`size`) VALUES ('".hesk_dbEscape($tmpvar['trackid'])."','".hesk_dbEscape($myatt['saved_name'])."','".hesk_dbEscape($myatt['real_name'])."','".intval($myatt['size'])."')"); + $tmpvar['attachments'] .= hesk_dbInsertID() . '#' . $myatt['real_name'] .','; + + $num++; + } + + if (strlen($tmpvar['attachmment_notices'])) + { + $tmpvar['message'] .= "

    " . hesk_input($hesklang['attrem'],'','',1) . "
    " . nl2br(hesk_input($tmpvar['attachmment_notices'],'','',1)); + } + } + + // Delete the temporary files + deleteAll($results['tempdir']); + + // If this is a reply add a new reply + if ($is_reply) + { + // Set last replier name to customer name + $ticket['lastreplier'] = ($tmpvar['name'] == $hesklang['pde']) ? $tmpvar['email'] : $tmpvar['name'];; + + // If staff hasn't replied yet, keep ticket status "New", otherwise set it to "Waiting reply from staff" + $ticket['status'] = $ticket['status'] ? 1 : 0; + + // Update ticket as necessary + hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` SET `lastchange`=NOW(),`status`='{$ticket['status']}',`lastreplier`='0' WHERE `id`='".intval($ticket['id'])."' LIMIT 1"); + + // Insert reply into database + hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."replies` (`replyto`,`name`,`message`,`dt`,`attachments`) VALUES ('".intval($ticket['id'])."','".hesk_dbEscape($ticket['lastreplier'])."','".hesk_dbEscape($tmpvar['message'])."',NOW(),'".hesk_dbEscape($tmpvar['attachments'])."')"); + + // --> Prepare reply message + + // 1. Generate the array with ticket info that can be used in emails + $info = array( + 'email' => $ticket['email'], + 'category' => $ticket['category'], + 'priority' => $ticket['priority'], + 'owner' => $ticket['owner'], + 'trackid' => $ticket['trackid'], + 'status' => $ticket['status'], + 'name' => $ticket['name'], + 'lastreplier' => $ticket['lastreplier'], + 'subject' => $ticket['subject'], + 'message' => stripslashes($tmpvar['message']), + 'attachments' => $tmpvar['attachments'], + 'dt' => hesk_date($ticket['dt'], true), + 'lastchange' => hesk_date($ticket['lastchange'], true), + ); + + // 2. Add custom fields to the array + foreach ($hesk_settings['custom_fields'] as $k => $v) + { + $info[$k] = $v['use'] ? $ticket[$k] : ''; + } + + // 3. Make sure all values are properly formatted for email + $ticket = hesk_ticketToPlain($info, 1, 0); + + // --> Process custom fields before sending + foreach ($hesk_settings['custom_fields'] as $k => $v) + { + $ticket[$k] = $v['use'] ? hesk_msgToPlain($ticket[$k], 1) : ''; + } + + // --> If ticket is assigned just notify the owner + if ($ticket['owner']) + { + hesk_notifyAssignedStaff(false, 'new_reply_by_customer', 'notify_reply_my'); + } + // --> No owner assigned, find and notify appropriate staff + else + { + hesk_notifyStaff('new_reply_by_customer',"`notify_reply_unassigned`='1'"); + } + + return $ticket['trackid']; + + } // END REPLY + + // Not a reply, but a new ticket. Add it to the database + $tmpvar['category'] = 1; + $tmpvar['priority'] = 3; + $_SERVER['REMOTE_ADDR'] = $hesklang['unknown']; + + // Auto assign tickets if aplicable + $tmpvar['owner'] = 0; + $tmpvar['history'] = $pop3 ? sprintf($hesklang['thist16'], hesk_date()) : sprintf($hesklang['thist11'], hesk_date()); + + $autoassign_owner = hesk_autoAssignTicket($tmpvar['category']); + + #print_r($autoassign_owner); + + if ($autoassign_owner) + { + $tmpvar['owner'] = $autoassign_owner['id']; + $tmpvar['history'] .= sprintf($hesklang['thist10'],hesk_date(),$autoassign_owner['name'].' ('.$autoassign_owner['user'].')'); + } + + // Custom fields will be empty as there is no reliable way of detecting them + foreach ($hesk_settings['custom_fields'] as $k=>$v) + { + $tmpvar[$k] = ''; + } + + // Insert ticket to database + $ticket = hesk_newTicket($tmpvar); + + // Notify the customer + hesk_notifyCustomer(); + + // Need to notify staff? + // --> From autoassign? + if ($tmpvar['owner'] && $autoassign_owner['notify_assigned']) + { + hesk_notifyAssignedStaff($autoassign_owner, 'ticket_assigned_to_you'); + } + // --> No autoassign, find and notify appropriate staff + elseif ( ! $tmpvar['owner'] ) + { + hesk_notifyStaff('new_ticket_staff', " `notify_new_unassigned` = '1' "); + } + + return $ticket['trackid']; +} // END hesk_email2ticket() + + +function hesk_encodeUTF8($in, $encoding) +{ + $encoding = strtoupper($encoding); + + switch($encoding) + { + case 'UTF-8': + return $in; + break; + case 'ISO-8859-1': + return utf8_encode($in); + break; + default: + return iconv($encoding, 'UTF-8', $in); + break; + } +} // END hesk_encodeUTF8() + + +function hesk_stripQuotedText($message) +{ + global $hesk_settings, $hesklang; + + // Stripping quoted text disabled? + if ( ! $hesk_settings['strip_quoted']) + { + return $message; + } + + // Loop through available languages and ty to find the tag + foreach ($hesk_settings['languages'] as $language => $settings) + { + if ( ($found = strpos($message, $settings['hr']) ) !== false ) + { + // "Reply above this line" tag found, strip quoted reply + $message = substr($message, 0, $found); + $message .= "\n" . $hesklang['qrr']; + + // Set language to the detected language + hesk_setLanguage($language); + break; + } + } + + return $message; +} // END hesk_stripQuotedText() + + +function hesk_isReturnedEmail($tmpvar) +{ + // Check noreply email addresses + if ( preg_match('/not?[\-_]reply@/i', $tmpvar['email']) ) + { + return true; + } + + // Check mailer daemon email addresses + if ( preg_match('/mail(er)?[\-_]daemon@/i', $tmpvar['email']) ) + { + return true; + } + + // Check autoreply subjects + if ( preg_match('/^[\[\(]?Auto(mat(ic|ed))?[ \-]?reply/i', $tmpvar['subject']) ) + { + return true; + } + + // Check out of office subjects + if ( preg_match('/^Out of Office/i', $tmpvar['subject']) ) + { + return true; + } + + // Check delivery failed email subjects + if ( + preg_match('/DELIVERY FAILURE/i', $tmpvar['subject']) || + preg_match('/Undelivered Mail Returned to Sender/i', $tmpvar['subject']) || + preg_match('/Delivery Status Notification \(Failure\)/i', $tmpvar['subject']) || + preg_match('/Returned mail\: see transcript for details/i', $tmpvar['subject']) + ) + { + return true; + } + + // Check Mail Delivery sender name + if ( preg_match('/Mail[ \-_]?Delivery/i', $tmpvar['name']) ) + { + return true; + } + + // Check Delivery failed message + if ( preg_match('/postmaster@/i', $tmpvar['email']) && preg_match('/Delivery has failed to these recipients/i', $tmpvar['message']) ) + { + return true; + } + + // No pattern detected, seems like this is not a returned email + return false; + +} // END hesk_isReturnedEmail() + + +function hesk_isEmailLoop($email, $message_hash) +{ + global $hesk_settings, $hesklang, $hesk_db_link; + + // If $hesk_settings['loop_hits'] is set to 0 this function is disabled + if ( ! $hesk_settings['loop_hits']) + { + return false; + } + + // Escape wildcards in email + $email_like = hesk_dbEscape(hesk_dbLike($email)); + + // Delete expired DB entries + hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."pipe_loops` WHERE `dt` < (NOW() - INTERVAL ".intval($hesk_settings['loop_time'])." SECOND) "); + + // Check current entry + $res = hesk_dbQuery("SELECT `hits`, `message_hash` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."pipe_loops` WHERE `email` LIKE '{$email_like}' LIMIT 1"); + + // Any active entry* + if (hesk_dbNumRows($res)) + { + list($num, $md5) = hesk_dbFetchRow($res); + + $num++; + + // Number of emails in a time period reached? + if ($num >= $hesk_settings['loop_hits']) + { + return true; + } + + // Message exactly the same as in previous email? + if ($message_hash == $md5) + { + return true; + } + + // Update DB entry + hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."pipe_loops` SET `hits` = `hits` + 1, `message_hash` = '".hesk_dbEscape($message_hash)."' WHERE `email` LIKE '{$email_like}' LIMIT 1"); + } + else + { + // First instance, insert a new database row + hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."pipe_loops` (`email`, `message_hash`) VALUES ('".hesk_dbEscape($email)."', '".hesk_dbEscape($message_hash)."')"); + } + + // No loop rule trigered + return false; + +} // END hesk_isEmailLoop() + + +function hesk_cleanExit() +{ + global $results; + + // Delete the temporary files + deleteAll($results['tempdir']); + + // Return NULL + return NULL; +} // END hesk_cleanExit() From f000ebc729f338b27ee5392e7794c1bfcd7f987b Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Thu, 25 Sep 2014 21:50:13 -0400 Subject: [PATCH 067/208] #51 Fixed variable naming clash --- admin/index.php | 2 +- inc/header.inc.php | 14 +++++++------- inc/headerAdmin.inc.php | 4 ++-- inc/show_admin_nav.inc.php | 28 ++++++++++++++-------------- 4 files changed, 24 insertions(+), 24 deletions(-) diff --git a/admin/index.php b/admin/index.php index a4031e58..f5bab287 100644 --- a/admin/index.php +++ b/admin/index.php @@ -280,7 +280,7 @@ function print_login()
    -
    +
    ';} else { echo '
    ';}?>
    diff --git a/inc/header.inc.php b/inc/header.inc.php index 56edd27f..ece16e76 100644 --- a/inc/header.inc.php +++ b/inc/header.inc.php @@ -135,9 +135,9 @@ if ($nuMods_settings['maintenance_mode'] && !defined('ON_MAINTENANCE_PAGE') && ! @@ -154,17 +154,17 @@ if ($nuMods_settings['show_icons']) {
    diff --git a/inc/headerAdmin.inc.php b/inc/headerAdmin.inc.php index 002d1ad5..a952af9c 100644 --- a/inc/headerAdmin.inc.php +++ b/inc/headerAdmin.inc.php @@ -131,8 +131,8 @@ require(HESK_PATH . 'nuMods_settings.inc.php'); diff --git a/inc/show_admin_nav.inc.php b/inc/show_admin_nav.inc.php index b6a9d544..bb4de4e5 100644 --- a/inc/show_admin_nav.inc.php +++ b/inc/show_admin_nav.inc.php @@ -51,17 +51,17 @@ $num_mail = hesk_checkNewMail();
    From ea5947c6c1ddda312d764a265193a8b7199bed69 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sat, 27 Sep 2014 11:22:59 -0400 Subject: [PATCH 068/208] Closes #50: Don't re-index statuses until after everything has been updated --- admin/admin_settings_save.php | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/admin/admin_settings_save.php b/admin/admin_settings_save.php index 50cb4680..de2e9438 100644 --- a/admin/admin_settings_save.php +++ b/admin/admin_settings_save.php @@ -403,6 +403,7 @@ for ($i=1;$i<=20;$i++) //-- Update the statuses hesk_dbConnect(); +$wasStatusDeleted = false; //-- Get all the status IDs $statusesSql = 'SELECT * FROM `'.$hesk_settings['db_pfix'].'statuses`'; $results = hesk_dbQuery($statusesSql); @@ -415,19 +416,7 @@ while ($row = $results->fetch_assoc()) $stmt = hesk_dbConnect()->prepare($delete); $stmt->bind_param('i', $row['ID']); $stmt->execute(); - - //-- In case we deleted a status in the middle, we now need to re-index the other IDs. - $reIndexQuery = 'SELECT * FROM `'.hesk_dbEscape($hesk_settings['db_pfix']).'statuses` WHERE `ID` > '.$row['ID']; - $reIndexRS = hesk_dbQuery($reIndexQuery); - //-- Update each ID by subtracting 1 - $reIndexQuery = 'UPDATE `'.hesk_dbEscape($hesk_settings['db_pfix']).'statuses` SET `ID` = ? WHERE `ID` = ?'; - while ($row = $reIndexRS->fetch_assoc()) - { - $stmt = hesk_dbConnect()->prepare($reIndexQuery); - $newID = $row['ID'] - 1; - $stmt->bind_param('ii', $newID, $row['ID']); - $stmt->execute(); - } + $wasStatusDeleted = true; } else { //-- Update the information in the database with what is on the page @@ -439,6 +428,16 @@ while ($row = $results->fetch_assoc()) } } +//-- If any statuses were deleted, re-index them before adding a new one +if ($wasStatusDeleted) { + //-- First drop and re-add the ID column + hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."statuses` DROP COLUMN `ID`"); + hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."statuses` ADD `ID` INT NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST"); + + //-- Since statuses should be zero-based, but are now one-based, subtract one from each ID + hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."statuses` SET `ID` = `ID`-1"); +} + //-- Insert the addition if there is anything to add if ($_POST['sN_shortName'] != null && $_POST['sN_longName'] != null && $_POST['sN_textColor'] != null) { From 69f7636fa5ae5c1d5c76b2b8480d876e601f4599 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sat, 27 Sep 2014 11:44:03 -0400 Subject: [PATCH 069/208] Closes #31 e-mail is no longer required for staff --- admin/admin_submit_ticket.php | 4 ++-- admin/admin_ticket.php | 6 ++++-- admin/new_ticket.php | 4 ++-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/admin/admin_submit_ticket.php b/admin/admin_submit_ticket.php index 4310f94d..8b229636 100644 --- a/admin/admin_submit_ticket.php +++ b/admin/admin_submit_ticket.php @@ -63,7 +63,7 @@ if ( empty($_POST) && ! empty($_SERVER['CONTENT_LENGTH']) ) $hesk_error_buffer = array(); $tmpvar['name'] = hesk_input( hesk_POST('name') ) or $hesk_error_buffer['name']=$hesklang['enter_your_name']; -$tmpvar['email'] = hesk_validateEmail( hesk_POST('email'), 'ERR', 0) or $hesk_error_buffer['email']=$hesklang['enter_valid_email']; +$tmpvar['email'] = hesk_POST('email'); $tmpvar['category'] = intval( hesk_POST('category') ) or $hesk_error_buffer['category']=$hesklang['sel_app_cat']; $tmpvar['priority'] = intval( hesk_POST('priority') ); @@ -178,7 +178,7 @@ elseif (hesk_checkPermission('can_assign_self',0) && hesk_okCategory($tmpvar['ca } // Notify customer of the ticket? -$notify = ! empty($_POST['notify']) ? 1 : 0; +$notify = (!empty($_POST['notify']) && !empty($tmpvar['email']) ) ? 1 : 0; // Show ticket after submission? $show = ! empty($_POST['show']) ? 1 : 0; diff --git a/admin/admin_ticket.php b/admin/admin_ticket.php index 622d7814..478709e3 100644 --- a/admin/admin_ticket.php +++ b/admin/admin_ticket.php @@ -1265,8 +1265,10 @@ function hesk_printReplyForm() {

    ()
    -

    - +

    + '; + } ?> diff --git a/admin/new_ticket.php b/admin/new_ticket.php index 8fdc44eb..0c140113 100644 --- a/admin/new_ticket.php +++ b/admin/new_ticket.php @@ -119,8 +119,8 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
    - ';} elseif (in_array('email',$_SESSION['isnotice'])) {echo '
    ';} else {echo '
    ';} ?> - +
    +
    placeholder=""/>
    From a4fa98d01028b94871c21fdbebebd51f50177c11 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sat, 27 Sep 2014 15:13:26 -0400 Subject: [PATCH 070/208] #39 Ticket screen now shows parent/children of that ticket --- admin/admin_ticket.php | 29 +++++++++++++++++++++++++++++ install/updateTo1-4-0.php | 5 +++-- language/en/text.php | 3 +++ 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/admin/admin_ticket.php b/admin/admin_ticket.php index 478709e3..c84443f4 100644 --- a/admin/admin_ticket.php +++ b/admin/admin_ticket.php @@ -500,6 +500,35 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php'); } ?>
  • +
  • + +

    fetch_assoc(); + echo ''.$parent['trackid'].''; + } else { + echo $hesklang['none']; + } + ?>

    +
  • +
  • + +

    fetch_assoc()) { + $hasRows = true; + echo ''.$row['trackid'].'
    '; + } + if (!$hasRows) { + echo $hesklang['none']; + } + ?>

    +
  • diff --git a/install/updateTo1-4-0.php b/install/updateTo1-4-0.php index e2d4dddd..c8ff8bd5 100644 --- a/install/updateTo1-4-0.php +++ b/install/updateTo1-4-0.php @@ -4,11 +4,12 @@ define('HESK_PATH','../'); require(HESK_PATH . 'install/install_functions.inc.php'); require(HESK_PATH . 'hesk_settings.inc.php'); hesk_dbConnect(); -hesk_dbQuery("CREATE TABLE `".$hesk_settings['db_pfix']."denied_ips` ( +hesk_dbQuery("CREATE TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."denied_ips` ( `ID` INT NOT NULL PRIMARY KEY AUTO_INCREMENT, `RangeStart` VARCHAR(100) NOT NULL, `RangeEnd` VARCHAR(100) NOT NULL)"); -hesk_dbQuery("CREATE TABLE `".$hesk_settings['db_pfix']."denied_emails` (ID INT NOT NULL PRIMARY KEY AUTO_INCREMENT, Email VARCHAR(100) NOT NULL PRIMARY KEY);"); +hesk_dbQuery("CREATE TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."denied_emails` (ID INT NOT NULL PRIMARY KEY AUTO_INCREMENT, Email VARCHAR(100) NOT NULL PRIMARY KEY);"); +hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` ADD COLUMN `parent` MEDIUMINT(8) NULL AFTER `custom20`;"); ?>

    Update complete!

    diff --git a/language/en/text.php b/language/en/text.php index 52378770..e659d01b 100644 --- a/language/en/text.php +++ b/language/en/text.php @@ -59,6 +59,9 @@ $hesklang['email_bans'] = 'Email Bans'; $hesklang['ip_email_bans'] = 'IP / Email Bans'; $hesklang['ip_banned'] = 'Your IP has been banned by the help desk. You will be unable to submit a ticket until your IP ban has been removed.'; $hesklang['email_banned'] = 'The email address you have entered has been banned by the help desk. You will be unable to submit a ticket until your email ban has been removed.'; +$hesklang['none'] = 'None'; +$hesklang['parent'] = 'Parent'; +$hesklang['children'] = 'Children'; // ADDED OR MODIFIED IN NuMods 1.3.1 $hesklang['autorefresh'] = 'Autorefresh:'; From 3151ece7dfac0f4dd6193bb83f3a8fee6a634579 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sat, 27 Sep 2014 22:14:49 -0400 Subject: [PATCH 071/208] #39 making more progress on parent/child relationships Still need to update childs when merging/deleting tickets, and need to add the ability to assign its parent, and to delete a parent/child relationship --- admin/admin_ticket.php | 53 +++++++++++++++++++++++++++++++++++++++++ js/nuMods-javascript.js | 10 ++++++++ language/en/text.php | 5 ++++ 3 files changed, 68 insertions(+) diff --git a/admin/admin_ticket.php b/admin/admin_ticket.php index c84443f4..5a4eee24 100644 --- a/admin/admin_ticket.php +++ b/admin/admin_ticket.php @@ -309,6 +309,42 @@ if ( ($can_reply || $can_edit) && isset($_POST['h']) && isset($_POST['m']) && is hesk_process_messages($hesklang['twu'],'admin_ticket.php?track='.$trackingID.'&Refresh='.mt_rand(10000,99999),'SUCCESS'); } +/* Add child action */ +if (($can_reply || $can_edit) && isset($_POST['childTrackingId'])) { + //-- Make sure this isn't the same ticket or one of its merged tickets. + $mergedTickets = hesk_dbQuery('SELECT * FROM `'.hesk_dbEscape($hesk_settings['db_pfix']).'tickets` WHERE `trackid` = + \''.hesk_dbEscape($trackingID).'\' AND `merged` LIKE \'#'.hesk_dbEscape($_POST['childTrackingId']).'\''); + if ($_POST['childTrackingId'] == $trackingID || $mergedTickets->num_rows > 0) { + hesk_process_messages($hesklang['child_is_itself'], 'admin_ticket.php?track='.$trackingID.'&Refresh='.mt_rand(10000,99999)); + } + + //-- Does the child exist? + $existRs = hesk_dbQuery('SELECT * FROM `'.hesk_dbEscape($hesk_settings['db_pfix']).'tickets` WHERE `trackid` = \''.hesk_dbEscape($_POST['childTrackingId']).'\''); + if ($existRs->num_rows == 0) { + //-- Maybe it was merged? + $existRs = hesk_dbQuery('SELECT `trackid` FROM `'.hesk_dbEscape($hesk_settings['db_pfix']).'tickets` WHERE `merged` LIKE \'#'.hesk_dbEscape($_POST['childTrackingId']).'#\''); + if ($existRs->num_rows > 0) { + //-- Yes, it was merged. Set the child to the "new" ticket; not the merged one. + $exist = $existRs->fetch_assoc(); + $_POST['childTrackingId'] = $exist['trackid']; + } else { + hesk_process_messages(sprintf($hesklang['child_does_not_exist'], $_POST['childTrackingId']), 'admin_ticket.php?track='.$trackingID.'&Refresh='.mt_rand(10000,99999)); + } + } + + //-- Check if the ticket is already a child. + $childRs = hesk_dbQuery('SELECT * FROM `'.hesk_dbEscape($hesk_settings['db_pfix']).'tickets` WHERE `parent` = '.$ticket['id'].' AND `trackid` = \''.$_POST['childTrackingId'].'\''); + if ($childRs->num_rows > 0) { + hesk_process_messages(sprintf($hesklang['is_child_already'], $_POST['childTrackingId']), 'admin_ticket.php?track='.$trackingID.'&Refresh='.mt_rand(10000,99999), 'NOTICE'); + } + + hesk_dbQuery('UPDATE `'.hesk_dbEscape($hesk_settings['db_pfix']).'tickets` SET `parent` = '.$ticket['id'].' WHERE `trackid` = \''.$_POST['childTrackingId'].'\''); + hesk_process_messages(sprintf($hesklang['child_added'], $_POST['childTrackingId']), 'admin_ticket.php?track='.$trackingID.'&Refresh='.mt_rand(10000,99999), 'SUCCESS'); +} + +/* Delete child action */ +//TODO Populate this + /* Delete attachment action */ if (isset($_GET['delatt']) && hesk_token_check()) { @@ -528,6 +564,23 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php'); echo $hesklang['none']; } ?>

    + +

    '.$hesklang['add_child'].''; ?>

    + + diff --git a/js/nuMods-javascript.js b/js/nuMods-javascript.js index 71d1bb31..2ac14462 100644 --- a/js/nuMods-javascript.js +++ b/js/nuMods-javascript.js @@ -40,4 +40,14 @@ function toggleFilterCheckboxes(show) { } } +function toggleChildrenForm(show) { + if (show) { + $('#childrenForm').show(); + $('#addChildText').hide(); + } else { + $('#childrenForm').hide(); + $('#addChildText').show(); + } +} + jQuery(document).ready(loadJquery); diff --git a/language/en/text.php b/language/en/text.php index e659d01b..ff2bd438 100644 --- a/language/en/text.php +++ b/language/en/text.php @@ -62,6 +62,11 @@ $hesklang['email_banned'] = 'The email address you have entered has been banned $hesklang['none'] = 'None'; $hesklang['parent'] = 'Parent'; $hesklang['children'] = 'Children'; +$hesklang['add_child'] = 'Add Child'; +$hesklang['child_added'] = 'Successfully added %s as a child to this ticket.'; //%s: the child tracking ID +$hesklang['is_child_already'] = '%s is already a child of this ticket.'; //%s: the child tracking ID +$hesklang['child_does_not_exist'] = '%s is not a valid Tracking ID!'; //%s: the child tracking ID +$hesklang['child_is_itself'] = 'You cannot set a ticket as a child of itself.'; // ADDED OR MODIFIED IN NuMods 1.3.1 $hesklang['autorefresh'] = 'Autorefresh:'; From 18553868781e764c9cf0706d478d5a1de49a0ea9 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 28 Sep 2014 00:07:25 -0400 Subject: [PATCH 072/208] Closes #39 - finished parent/child relationships --- admin/admin_ticket.php | 24 +++++++++++++++++++----- language/en/text.php | 2 ++ 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/admin/admin_ticket.php b/admin/admin_ticket.php index 5a4eee24..b409b924 100644 --- a/admin/admin_ticket.php +++ b/admin/admin_ticket.php @@ -313,7 +313,7 @@ if ( ($can_reply || $can_edit) && isset($_POST['h']) && isset($_POST['m']) && is if (($can_reply || $can_edit) && isset($_POST['childTrackingId'])) { //-- Make sure this isn't the same ticket or one of its merged tickets. $mergedTickets = hesk_dbQuery('SELECT * FROM `'.hesk_dbEscape($hesk_settings['db_pfix']).'tickets` WHERE `trackid` = - \''.hesk_dbEscape($trackingID).'\' AND `merged` LIKE \'#'.hesk_dbEscape($_POST['childTrackingId']).'\''); + \''.hesk_dbEscape($trackingID).'\' AND `merged` LIKE \'%#'.hesk_dbEscape($_POST['childTrackingId']).'#%\''); if ($_POST['childTrackingId'] == $trackingID || $mergedTickets->num_rows > 0) { hesk_process_messages($hesklang['child_is_itself'], 'admin_ticket.php?track='.$trackingID.'&Refresh='.mt_rand(10000,99999)); } @@ -343,7 +343,16 @@ if (($can_reply || $can_edit) && isset($_POST['childTrackingId'])) { } /* Delete child action */ -//TODO Populate this +if (($can_reply || $can_edit) && isset($_GET['deleteChild'])) { + //-- Delete the relationship + hesk_dbQuery('UPDATE `'.hesk_dbEscape($hesk_settings['db_pfix']).'tickets` SET `parent` = NULL WHERE `ID` = '.hesk_dbEscape($_GET['deleteChild'])); + hesk_process_messages($hesklang['relationship_deleted'], 'admin_ticket.php?track='.$trackingID.'&Refresh='.mt_rand(10000,99999), 'SUCCESS'); + +} elseif (($can_reply || $can_edit) && isset($_GET['deleteParent'])) { + //-- Delete the relationship + hesk_dbQuery('UPDATE `'.hesk_dbEscape($hesk_settings['db_pfix']).'tickets` SET `parent` = NULL WHERE `ID` = '.hesk_dbEscape($ticket['id'])); + hesk_process_messages($hesklang['relationship_deleted'], 'admin_ticket.php?track='.$trackingID.'&Refresh='.mt_rand(10000,99999), 'SUCCESS'); +} /* Delete attachment action */ if (isset($_GET['delatt']) && hesk_token_check()) @@ -543,7 +552,9 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php'); //-- Get the tracking ID of the parent $parent = hesk_dbQuery('SELECT `trackid` FROM `'.hesk_dbEscape($hesk_settings['db_pfix']).'tickets` WHERE `ID` = '.hesk_dbEscape($ticket['parent']))->fetch_assoc(); - echo ''.$parent['trackid'].''; + echo ' + '; + echo ' '.$parent['trackid'].''; } else { echo $hesklang['none']; } @@ -554,11 +565,14 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');

    fetch_assoc()) { $hasRows = true; - echo ''.$row['trackid'].'
    '; + echo ' + '; + echo ' '.$row['trackid'].''; + echo '
    '; } if (!$hasRows) { echo $hesklang['none']; diff --git a/language/en/text.php b/language/en/text.php index ff2bd438..1b3f6dd0 100644 --- a/language/en/text.php +++ b/language/en/text.php @@ -67,6 +67,8 @@ $hesklang['child_added'] = 'Successfully added %s as a child to $hesklang['is_child_already'] = '%s is already a child of this ticket.'; //%s: the child tracking ID $hesklang['child_does_not_exist'] = '%s is not a valid Tracking ID!'; //%s: the child tracking ID $hesklang['child_is_itself'] = 'You cannot set a ticket as a child of itself.'; +$hesklang['delete_relationship'] = 'Delete Relationship'; +$hesklang['relationship_deleted'] = 'Parent/Child relationship deleted.'; // ADDED OR MODIFIED IN NuMods 1.3.1 $hesklang['autorefresh'] = 'Autorefresh:'; From 77eb9188b6eff2e5fdc02c00bd123cadde641d92 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 28 Sep 2014 00:51:06 -0400 Subject: [PATCH 073/208] Updated update scripts/files --- install/updateNuMods.php | 6 +++--- install/updateTo1-3-1.php | 7 +++---- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/install/updateNuMods.php b/install/updateNuMods.php index 29e6964f..be494795 100644 --- a/install/updateNuMods.php +++ b/install/updateNuMods.php @@ -3,7 +3,6 @@ define('IN_SCRIPT',1); define('HESK_PATH','../'); require(HESK_PATH . 'install/install_functions.inc.php'); require(HESK_PATH . 'hesk_settings.inc.php'); - $showFinished = 'none'; $showInstructions = 'block'; if ($_GET['update'] == 1) @@ -70,16 +69,17 @@ if ($_GET['update'] == 1)

    Update here. Do not use any of the other links below!

    Update NuMods from v1.2.4 - v1.3.0 to v1.4.0

    Update here. Do not use the installation below!

    -

    Install NuMods v1.3.1 for the first time

    +

    Install NuMods v1.4.0 for the first time

    If you have not yet installed/updated HESK, please do so first before continuing; otherwise installation will fail!


    -

    Please verify the database information below. Additionally, ensure that the database user has CREATE permissions.

    +

    Please verify the database information below. Additionally, ensure that the database user has CREATE and ALTER permissions.

    Database Host:

    Database Name:

    Database User:

    Database Password:

    Database Prefix:

    Proceed with installation +

    By proceeding, you agree to the terms of the Creative Commons Attribution-ShareAlike 4.0 International License.

    Installation Finished

    diff --git a/install/updateTo1-3-1.php b/install/updateTo1-3-1.php index 59d03bc8..82419dfc 100644 --- a/install/updateTo1-3-1.php +++ b/install/updateTo1-3-1.php @@ -5,7 +5,6 @@ require(HESK_PATH . 'install/install_functions.inc.php'); require(HESK_PATH . 'hesk_settings.inc.php'); hesk_dbConnect(); hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."users` ADD COLUMN `autorefresh` BIGINT NOT NULL DEFAULT 0 AFTER `replies`;"); -?> - -

    Update complete!

    -

    Please delete the install folder for security reasons, and then proceed back to the Help Desk

    \ No newline at end of file +header('Location: updateTo1-4-0.php'); +exit(); +?> \ No newline at end of file From a05a56fd3e981ece96e2a27de23616fa1be1704f Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 28 Sep 2014 00:58:54 -0400 Subject: [PATCH 074/208] Updated version numbers --- README.md | 2 +- nuMods_settings.inc.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index dff9cd5c..9cc8dac6 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ [![Stories in Ready](https://badge.waffle.io/mkoch227/numods.png?label=ready&title=Ready)](https://waffle.io/mkoch227/numods) -

    NuMods v1.3.0

    +

    NuMods v1.4.0

    This branch contains all files modified from the base version of HESK to become NuMods, a set of modifications for HESK v2.x diff --git a/nuMods_settings.inc.php b/nuMods_settings.inc.php index 27cc9ede..ba69b175 100644 --- a/nuMods_settings.inc.php +++ b/nuMods_settings.inc.php @@ -23,4 +23,4 @@ $nuMods_settings['show_icons'] = 0; $nuMods_settings['maintenance_mode'] = 0; /* DO NOT EDIT ANYTHING BELOW THIS LINE */ -$nuMods_settings['version']= '1.3.0'; \ No newline at end of file +$nuMods_settings['version']= '1.4.0'; \ No newline at end of file From 616647e42ae7e7998c3330101b4d6ee27999d29c Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 28 Sep 2014 01:02:36 -0400 Subject: [PATCH 075/208] I never made 1.3.1 a release --- language/en/text.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/language/en/text.php b/language/en/text.php index 1b3f6dd0..9852b9d1 100644 --- a/language/en/text.php +++ b/language/en/text.php @@ -69,8 +69,6 @@ $hesklang['child_does_not_exist'] = '%s is not a valid Tracking $hesklang['child_is_itself'] = 'You cannot set a ticket as a child of itself.'; $hesklang['delete_relationship'] = 'Delete Relationship'; $hesklang['relationship_deleted'] = 'Parent/Child relationship deleted.'; - -// ADDED OR MODIFIED IN NuMods 1.3.1 $hesklang['autorefresh'] = 'Autorefresh:'; $hesklang['autorefresh_restrictions'] = 'Enter value in milliseconds. Value must be greater than 1000 to use this feature. No fractional values.'; From 511ff23d22f4f8c91bfa7d6c7ef71d03a199c3fa Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 28 Sep 2014 01:03:44 -0400 Subject: [PATCH 076/208] Update README.md --- README.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9cc8dac6..6932e504 100644 --- a/README.md +++ b/README.md @@ -4,10 +4,15 @@ This branch contains all files modified from the base version of HESK to become NuMods, a set of modifications for HESK v2.x

    Features

    -

    Currently, the two major features of NuMods are:

    • A new, responsive user interface
    • Ability to create custom ticket statuses
    • +
    • Ability to ban IP addresses / email addresses
    • +
    • Right-to-left text direction
    • +
    • Designate parent/child relationships for tickets
    • +
    • Dynamically add columns to the ticket dashboard
    • +
    • Maintenance Mode
    • +
    • Ticket Dashboard Automatic Refresh

    Download

    @@ -33,7 +38,7 @@ You can download this tweak via two ways:

    Languages

    As of current, only English is a supported language, as there have been several language items that have been edited/created. If you want to translate NuMods to your own language, it is recommended to download the original HESK language file for your language, and then add/edit the lines listed under //Added or modified in HESK UI and //Added or modified in NuMods X.X.X (where X.X.X is a version number) for your language.

    -

    If you create a translation for NuMods, please submit it via a pull request or via the PHP Junkyards forum, where it will be committed to this branch.

    +

    NuMods translations are available at http://numods.mkochcs.com/download.php.

    Browser Compability

    This list may be incomplete. Please leave a note on the PHP Junkyard forums for additional browser compatibility information. From 5f70187de0d710ecd1a5a6f36598c871dd19306b Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 28 Sep 2014 01:12:53 -0400 Subject: [PATCH 077/208] Version 1.3.1 was never released --- install/updateNuMods.php | 4 +--- install/updateTo1-3-1.php | 10 ---------- install/updateTo1-4-0.php | 1 + 3 files changed, 2 insertions(+), 13 deletions(-) delete mode 100644 install/updateTo1-3-1.php diff --git a/install/updateNuMods.php b/install/updateNuMods.php index be494795..649df7b4 100644 --- a/install/updateNuMods.php +++ b/install/updateNuMods.php @@ -65,10 +65,8 @@ if ($_GET['update'] == 1)

    -

    Update NuMods from v1.3.1 to v1.4.0

    -

    Update here. Do not use any of the other links below!

    Update NuMods from v1.2.4 - v1.3.0 to v1.4.0

    -

    Update here. Do not use the installation below!

    +

    Update here. Do not use the installation below!

    Install NuMods v1.4.0 for the first time

    If you have not yet installed/updated HESK, please do so first before continuing; otherwise installation will fail!


    diff --git a/install/updateTo1-3-1.php b/install/updateTo1-3-1.php deleted file mode 100644 index 82419dfc..00000000 --- a/install/updateTo1-3-1.php +++ /dev/null @@ -1,10 +0,0 @@ - \ No newline at end of file diff --git a/install/updateTo1-4-0.php b/install/updateTo1-4-0.php index c8ff8bd5..d6908d38 100644 --- a/install/updateTo1-4-0.php +++ b/install/updateTo1-4-0.php @@ -4,6 +4,7 @@ define('HESK_PATH','../'); require(HESK_PATH . 'install/install_functions.inc.php'); require(HESK_PATH . 'hesk_settings.inc.php'); hesk_dbConnect(); +hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."users` ADD COLUMN `autorefresh` BIGINT NOT NULL DEFAULT 0 AFTER `replies`;"); hesk_dbQuery("CREATE TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."denied_ips` ( `ID` INT NOT NULL PRIMARY KEY AUTO_INCREMENT, `RangeStart` VARCHAR(100) NOT NULL, From 1ad5d5c063c8be15077ef818d498629b88b359d7 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 28 Sep 2014 10:13:57 -0400 Subject: [PATCH 078/208] Fixed SQL query --- install/{updateTo1-4-0.php => updateTo1-4-1.php} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename install/{updateTo1-4-0.php => updateTo1-4-1.php} (89%) diff --git a/install/updateTo1-4-0.php b/install/updateTo1-4-1.php similarity index 89% rename from install/updateTo1-4-0.php rename to install/updateTo1-4-1.php index d6908d38..f934fbf6 100644 --- a/install/updateTo1-4-0.php +++ b/install/updateTo1-4-1.php @@ -9,7 +9,7 @@ hesk_dbQuery("CREATE TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."denied_i `ID` INT NOT NULL PRIMARY KEY AUTO_INCREMENT, `RangeStart` VARCHAR(100) NOT NULL, `RangeEnd` VARCHAR(100) NOT NULL)"); -hesk_dbQuery("CREATE TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."denied_emails` (ID INT NOT NULL PRIMARY KEY AUTO_INCREMENT, Email VARCHAR(100) NOT NULL PRIMARY KEY);"); +hesk_dbQuery("CREATE TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."denied_emails` (ID INT NOT NULL PRIMARY KEY AUTO_INCREMENT, Email VARCHAR(100) NOT NULL);"); hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` ADD COLUMN `parent` MEDIUMINT(8) NULL AFTER `custom20`;"); ?> From 56612a492772b371b3565230318ea48e3f50fef5 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 28 Sep 2014 10:14:33 -0400 Subject: [PATCH 079/208] Updated version # --- README.md | 2 +- nuMods_settings.inc.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6932e504..5b5def5a 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ [![Stories in Ready](https://badge.waffle.io/mkoch227/numods.png?label=ready&title=Ready)](https://waffle.io/mkoch227/numods) -

    NuMods v1.4.0

    +

    NuMods v1.4.1

    This branch contains all files modified from the base version of HESK to become NuMods, a set of modifications for HESK v2.x diff --git a/nuMods_settings.inc.php b/nuMods_settings.inc.php index ba69b175..d5e88f84 100644 --- a/nuMods_settings.inc.php +++ b/nuMods_settings.inc.php @@ -23,4 +23,4 @@ $nuMods_settings['show_icons'] = 0; $nuMods_settings['maintenance_mode'] = 0; /* DO NOT EDIT ANYTHING BELOW THIS LINE */ -$nuMods_settings['version']= '1.4.0'; \ No newline at end of file +$nuMods_settings['version']= '1.4.1'; \ No newline at end of file From eab42588fba926ef2bb275c3d32ebaf3f59c48ae Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 28 Sep 2014 10:15:46 -0400 Subject: [PATCH 080/208] Added additional queries to base installation script --- install/updateNuMods.php | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/install/updateNuMods.php b/install/updateNuMods.php index 649df7b4..82f156d7 100644 --- a/install/updateNuMods.php +++ b/install/updateNuMods.php @@ -55,19 +55,26 @@ if ($_GET['update'] == 1) IsStaffClosedOption, IsStaffReopenedStatus, IsDefaultStaffReplyStatus, LockedTicketStatus) VALUES (5, 'on_hold', 'on_hold', '#000000', 0, 0, 0, 0, 0, 0, 0, 0);"); hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."users` ADD COLUMN `autorefresh` BIGINT NOT NULL DEFAULT 0 AFTER `replies`;"); + hesk_dbQuery("CREATE TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."denied_ips` ( + `ID` INT NOT NULL PRIMARY KEY AUTO_INCREMENT, + `RangeStart` VARCHAR(100) NOT NULL, + `RangeEnd` VARCHAR(100) NOT NULL)"); + hesk_dbQuery("CREATE TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."denied_emails` (ID INT NOT NULL PRIMARY KEY AUTO_INCREMENT, Email VARCHAR(100) NOT NULL);"); + hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` ADD COLUMN `parent` MEDIUMINT(8) NULL AFTER `custom20`;"); + } } ?> - NuMods 1.4.0 Install / Upgrade + NuMods 1.4.1 Install / Upgrade
    -

    Update NuMods from v1.2.4 - v1.3.0 to v1.4.0

    -

    Update here. Do not use the installation below!

    -

    Install NuMods v1.4.0 for the first time

    +

    Update NuMods from v1.2.4 - v1.3.0 to v1.4.1

    +

    Update here. Do not use the installation below!

    +

    Install NuMods v1.4.1 for the first time

    If you have not yet installed/updated HESK, please do so first before continuing; otherwise installation will fail!


    Please verify the database information below. Additionally, ensure that the database user has CREATE and ALTER permissions.

    From 16f7aedc97b42c6e305beb89797a4d94aa57f60e Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 28 Sep 2014 10:17:32 -0400 Subject: [PATCH 081/208] Update version # --- install/install_functions.inc.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install/install_functions.inc.php b/install/install_functions.inc.php index 3859f666..78ba56f7 100644 --- a/install/install_functions.inc.php +++ b/install/install_functions.inc.php @@ -37,7 +37,7 @@ if (!defined('IN_SCRIPT')) {die('Invalid attempt');} // We will be installing this HESK version: define('HESK_NEW_VERSION','2.5.5'); -define('NUMODS_NEW_VERSION','1.4.0'); +define('NUMODS_NEW_VERSION','1.4.1'); // Other required files and settings define('INSTALL',1); From df847c7e18899b0296976841750fc03903bfd53a Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 28 Sep 2014 10:24:36 -0400 Subject: [PATCH 082/208] Fixed update script for those who attempted the 1.4.0 installation --- install/updateNuMods.php | 1 + install/updateTo1-4-1.php | 13 ++++++++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/install/updateNuMods.php b/install/updateNuMods.php index 82f156d7..7dcb6ab6 100644 --- a/install/updateNuMods.php +++ b/install/updateNuMods.php @@ -73,6 +73,7 @@ if ($_GET['update'] == 1)

    Update NuMods from v1.2.4 - v1.3.0 to v1.4.1

    +

    If you attempted the v1.4.0 installation and it failed, use this update link. Do not use the link below!

    Update here. Do not use the installation below!

    Install NuMods v1.4.1 for the first time

    If you have not yet installed/updated HESK, please do so first before continuing; otherwise installation will fail!

    diff --git a/install/updateTo1-4-1.php b/install/updateTo1-4-1.php index f934fbf6..647cce67 100644 --- a/install/updateTo1-4-1.php +++ b/install/updateTo1-4-1.php @@ -4,11 +4,14 @@ define('HESK_PATH','../'); require(HESK_PATH . 'install/install_functions.inc.php'); require(HESK_PATH . 'hesk_settings.inc.php'); hesk_dbConnect(); -hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."users` ADD COLUMN `autorefresh` BIGINT NOT NULL DEFAULT 0 AFTER `replies`;"); -hesk_dbQuery("CREATE TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."denied_ips` ( - `ID` INT NOT NULL PRIMARY KEY AUTO_INCREMENT, - `RangeStart` VARCHAR(100) NOT NULL, - `RangeEnd` VARCHAR(100) NOT NULL)"); +if (!isset($_GET['ar'])) { + hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."users` ADD COLUMN `autorefresh` BIGINT NOT NULL DEFAULT 0 AFTER `replies`;"); + + hesk_dbQuery("CREATE TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."denied_ips` ( + `ID` INT NOT NULL PRIMARY KEY AUTO_INCREMENT, + `RangeStart` VARCHAR(100) NOT NULL, + `RangeEnd` VARCHAR(100) NOT NULL)"); +} hesk_dbQuery("CREATE TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."denied_emails` (ID INT NOT NULL PRIMARY KEY AUTO_INCREMENT, Email VARCHAR(100) NOT NULL);"); hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` ADD COLUMN `parent` MEDIUMINT(8) NULL AFTER `custom20`;"); ?> From e6db35fadf2510105cf5d7e3b21979d84cc3009f Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 12 Oct 2014 16:52:45 -0400 Subject: [PATCH 083/208] Closes #56: Responsified the ticket table --- inc/ticket_list.inc.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inc/ticket_list.inc.php b/inc/ticket_list.inc.php index 6078582b..a01d82fc 100644 --- a/inc/ticket_list.inc.php +++ b/inc/ticket_list.inc.php @@ -527,7 +527,7 @@ function hesk_print_list_head() { global $href, $query, $sort_possible, $hesklang, $hesk_settings; ?> -
    +
    From 18f9afb2237f2029c7815e5dd0cc51038ba7c990 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 12 Oct 2014 16:57:50 -0400 Subject: [PATCH 084/208] Closes #52: Contentified some hard-coded strings --- admin/admin_settings.php | 6 +++--- language/en/text.php | 5 +++++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/admin/admin_settings.php b/admin/admin_settings.php index 293f6b36..115e4af0 100644 --- a/admin/admin_settings.php +++ b/admin/admin_settings.php @@ -1797,7 +1797,7 @@ if ( defined('HESK_DEMO') )
    @@ -1812,7 +1812,7 @@ if ( defined('HESK_DEMO') )
    @@ -1826,7 +1826,7 @@ if ( defined('HESK_DEMO') )
    diff --git a/language/en/text.php b/language/en/text.php index 9852b9d1..99fda3c8 100644 --- a/language/en/text.php +++ b/language/en/text.php @@ -21,6 +21,11 @@ $hesklang['_COLLATE']='utf8_unicode_ci'; // This is the email break line that will be used in email piping $hesklang['EMAIL_HR']='------ Reply above this line ------'; +// ADDED OR MODIFIED IN NuMods 1.5.0 +$hesklang['display_rtl'] = 'Display site right-to-left'; +$hesklang['show_icons_navigation'] = 'Show icons on navigation bar'; +$hesklang['enable_maintenance'] = 'Enable maintenance mode'; + // ADDED OR MODIFIED IN NuMods 1.4.0 $hesklang['numods'] = 'NuMods'; $hesklang['navbarBackgroundColor'] = 'Navbar Background Color'; From bdbecd11e8059d0e175ad5054769f6b214abadad Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 12 Oct 2014 17:11:44 -0400 Subject: [PATCH 085/208] Closes #55: Email is no longer required on admin/edit_post.php --- admin/edit_post.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/edit_post.php b/admin/edit_post.php index 2a7295a5..730cd9d4 100644 --- a/admin/edit_post.php +++ b/admin/edit_post.php @@ -116,7 +116,7 @@ if (isset($_POST['save'])) else { $tmpvar['name'] = hesk_input( hesk_POST('name') ) or $hesk_error_buffer[]=$hesklang['enter_your_name']; - $tmpvar['email'] = hesk_validateEmail( hesk_POST('email'), 'ERR', 0) or $hesk_error_buffer[]=$hesklang['enter_valid_email']; + $tmpvar['email'] = hesk_validateEmail( hesk_POST('email'), 'ERR', 0); $tmpvar['subject'] = hesk_input( hesk_POST('subject') ) or $hesk_error_buffer[]=$hesklang['enter_ticket_subject']; $tmpvar['message'] = hesk_input( hesk_POST('message') ) or $hesk_error_buffer[]=$hesklang['enter_message']; From 473a30723612168315271ac24d1e20e83128c649 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 12 Oct 2014 20:20:29 -0400 Subject: [PATCH 086/208] Closes #53: The column width for the label text is now larger --- admin/admin_settings.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/admin/admin_settings.php b/admin/admin_settings.php index 115e4af0..633d9ce8 100644 --- a/admin/admin_settings.php +++ b/admin/admin_settings.php @@ -1788,13 +1788,13 @@ if ( defined('HESK_DEMO') )
    -
    @@ -691,7 +690,7 @@ function edit_user() + > '; } ?> diff --git a/inc/show_admin_nav.inc.php b/inc/show_admin_nav.inc.php index bb4de4e5..69b1546f 100644 --- a/inc/show_admin_nav.inc.php +++ b/inc/show_admin_nav.inc.php @@ -59,7 +59,7 @@ $num_mail = hesk_checkNewMail(); else {echo '
  •  '.$hesklang['menu_kb'].'
  • ';} if (hesk_checkPermission('can_run_reports',0)) {echo '
  •  '.$hesklang['reports'].'
  • ';} elseif (hesk_checkPermission('can_export',0)) {echo '
  •  '.$hesklang['reports'].'
  • ';} - if (hesk_checkPermission('can_man_settings',0)) {echo '
  •  '.$hesklang['settings'].'
  • ';} ?> + if (hesk_checkPermission('can_manage_settings',0)) {echo '
  •  '.$hesklang['settings'].'
  • ';} ?>
  • > 
  • >  Date: Fri, 24 Oct 2014 20:12:39 -0400 Subject: [PATCH 094/208] #59 Use an enum instead of a bit PHP/MySQL treats the bit in a really strange way...it just never works right --- install/updateTo1-5-0.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install/updateTo1-5-0.php b/install/updateTo1-5-0.php index 242faca6..8d37a73f 100644 --- a/install/updateTo1-5-0.php +++ b/install/updateTo1-5-0.php @@ -4,7 +4,7 @@ define('HESK_PATH','../'); require(HESK_PATH . 'install/install_functions.inc.php'); require(HESK_PATH . 'hesk_settings.inc.php'); hesk_dbConnect(); -hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."users` ADD COLUMN `active` BIT NOT NULL DEFAULT 1 AFTER `autorefresh`"); +hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."users` ADD COLUMN `active` ENUM('0', '1') NOT NULL DEFAULT 1 AFTER `autorefresh`"); hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."users` ADD COLUMN `can_manage_settings` INT NOT NULL DEFAULT 1"); ?> From 8fca201ad840a504b5c847577d271457d3630a2f Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Fri, 24 Oct 2014 20:13:31 -0400 Subject: [PATCH 095/208] Use an enum instead of an int --- install/updateTo1-5-0.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install/updateTo1-5-0.php b/install/updateTo1-5-0.php index 8d37a73f..ec7ef6e3 100644 --- a/install/updateTo1-5-0.php +++ b/install/updateTo1-5-0.php @@ -5,7 +5,7 @@ require(HESK_PATH . 'install/install_functions.inc.php'); require(HESK_PATH . 'hesk_settings.inc.php'); hesk_dbConnect(); hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."users` ADD COLUMN `active` ENUM('0', '1') NOT NULL DEFAULT 1 AFTER `autorefresh`"); -hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."users` ADD COLUMN `can_manage_settings` INT NOT NULL DEFAULT 1"); +hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."users` ADD COLUMN `can_manage_settings` ENUM('0', '1') NOT NULL DEFAULT 1"); ?>

    Update complete!

    From 8f27ba2c4867ce94d4a9bb9bb567c1ffe1dc50c7 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Fri, 24 Oct 2014 20:18:13 -0400 Subject: [PATCH 096/208] #59 Mark all current users as active Otherwise no one can log in --- install/updateTo1-5-0.php | 1 + 1 file changed, 1 insertion(+) diff --git a/install/updateTo1-5-0.php b/install/updateTo1-5-0.php index ec7ef6e3..8be6bf80 100644 --- a/install/updateTo1-5-0.php +++ b/install/updateTo1-5-0.php @@ -5,6 +5,7 @@ require(HESK_PATH . 'install/install_functions.inc.php'); require(HESK_PATH . 'hesk_settings.inc.php'); hesk_dbConnect(); hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."users` ADD COLUMN `active` ENUM('0', '1') NOT NULL DEFAULT 1 AFTER `autorefresh`"); +hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."users` SET `active` = 1"); hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."users` ADD COLUMN `can_manage_settings` ENUM('0', '1') NOT NULL DEFAULT 1"); ?> From 270a796090978bc7c41f10ee7e2d67e520e61e7f Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Fri, 24 Oct 2014 20:19:15 -0400 Subject: [PATCH 097/208] #59 Now the admin ticket page filters out inactive users --- admin/admin_ticket.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/admin_ticket.php b/admin/admin_ticket.php index 15c28201..1099df52 100644 --- a/admin/admin_ticket.php +++ b/admin/admin_ticket.php @@ -419,7 +419,7 @@ while ($row=hesk_dbFetchAssoc($result)) /* List of users */ $admins = array(); -$result = hesk_dbQuery("SELECT `id`,`name`,`isadmin`,`categories`,`heskprivileges` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."users` ORDER BY `id` ASC"); +$result = hesk_dbQuery("SELECT `id`,`name`,`isadmin`,`categories`,`heskprivileges` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."users` WHERE `active` = 1 ORDER BY `id` ASC"); while ($row=hesk_dbFetchAssoc($result)) { /* Is this an administrator? */ From 6c126ec78e8883603febefe92093bc09ea4d0e6d Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Fri, 24 Oct 2014 20:23:19 -0400 Subject: [PATCH 098/208] #59 We check for an active user on login --- admin/index.php | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/admin/index.php b/admin/index.php index f5bab287..f23f0ffe 100644 --- a/admin/index.php +++ b/admin/index.php @@ -197,10 +197,21 @@ function do_login() unset($_SESSION['pass']); + + /* Login successful, clean brute force attempts */ hesk_cleanBfAttempts(); - /* Regenerate session ID (security) */ + /* Make sure our user is active */ + if (!$_SESSION['active']) { + hesk_session_stop(); + $_SESSION['a_iserror'] = array('active'); + hesk_process_messages($hesklang['inactive_user'], 'NOREDIRECT'); + print_login(); + exit(); + } + + /* Regenerate session ID (security) */ hesk_session_regenerate_id(); /* Remember username? */ From e14e5f10500c9727e3eeb06634a95ea38c65233d Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Fri, 24 Oct 2014 22:15:39 -0400 Subject: [PATCH 099/208] #59 Partial implementation of active users on the manage users page --- admin/manage_users.php | 45 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/admin/manage_users.php b/admin/manage_users.php index 3d584d63..0eaebde9 100644 --- a/admin/manage_users.php +++ b/admin/manage_users.php @@ -79,6 +79,7 @@ $default_userdata = array( 'user' => '', 'signature' => '', 'isadmin' => 1, + 'active' => 1, 'categories' => array('1'), 'features' => array('can_view_tickets','can_reply_tickets','can_change_cat','can_assign_self','can_view_unassigned','can_view_online'), 'signature' => '', @@ -137,6 +138,7 @@ if ( $action = hesk_REQUEST('a') ) elseif ($action == 'save') {update_user();} elseif ($action == 'remove') {remove();} elseif ($action == 'autoassign') {toggle_autoassign();} + elseif ($action == 'active') {toggle_active();} else {hesk_error($hesklang['invalid_action']);} } @@ -427,6 +429,13 @@ while ($myuser = hesk_dbFetchAssoc($res)) $autoassign_code = ''; } + /* Is the user active? */ + if ($myuser['active']) { + $activeMarkup = '
    '; + } else { + $activeMarkup = ''; + } + echo <<
  • @@ -443,7 +452,7 @@ if ($hesk_settings['rating']) } echo <<$autoassign_code $edit_code $remove_code + EOC; @@ -533,7 +542,7 @@ function edit_user() if ( ! isset($_SESSION['save_userdata'])) { - $res = hesk_dbQuery("SELECT `user`,`pass`,`isadmin`,`name`,`email`,`signature`,`categories`,`autoassign`,`heskprivileges` AS `features`, `can_manage_settings` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."users` WHERE `id`='".intval($id)."' LIMIT 1"); + $res = hesk_dbQuery("SELECT `user`,`pass`,`isadmin`,`name`,`email`,`signature`,`categories`,`autoassign`,`heskprivileges` AS `features`, `can_manage_settings`, `active` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."users` WHERE `id`='".intval($id)."' LIMIT 1"); $_SESSION['userdata'] = hesk_dbFetchAssoc($res); /* Store original username for display until changes are saved successfully */ @@ -699,6 +708,9 @@ function edit_user() +
    + +
    @@ -1050,4 +1062,33 @@ function toggle_autoassign() hesk_process_messages($tmp,'./manage_users.php','SUCCESS'); } // End toggle_autoassign() + +function toggle_active() +{ + global $hesk_settings, $hesklang; + + /* Security check */ + hesk_token_check(); + + $myuser = intval(hesk_GET('id')) or hesk_error($hesklang['no_valid_id']); + $_SESSION['seluser'] = $myuser; + + if (intval(hesk_GET('s'))) + { + $active = 1; + $tmp = $hesklang['user_activated']; + } else + { + $active = 0; + $tmp = $hesklang['user_deactivated']; + } + + hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."users` SET `active` = '".$active."' WHERE `id` = '".intval($myuser)."'"); + + if (hesk_dbAffectedRows() != 1) { + hesk_process_messages($hesklang['int_error'].': '.$hesklang['user_not_found'],'./manage_users.php'); + } + + hesk_process_messages($tmp,'./manage_users.php','SUCCESS'); +} ?> From bee3b84855eb13536a93d67acfd54d2a8f69743f Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Fri, 24 Oct 2014 23:36:27 -0400 Subject: [PATCH 100/208] #59 Active users are now manageable --- admin/manage_users.php | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/admin/manage_users.php b/admin/manage_users.php index 0eaebde9..dd281e22 100644 --- a/admin/manage_users.php +++ b/admin/manage_users.php @@ -433,7 +433,7 @@ while ($myuser = hesk_dbFetchAssoc($res)) if ($myuser['active']) { $activeMarkup = ''; } else { - $activeMarkup = ''; + $activeMarkup = ''; } echo <<
    - +
    @@ -824,15 +824,18 @@ function update_user() $myuser = hesk_validateUserInfo(0,$_SERVER['PHP_SELF']); $myuser['id'] = $tmp; - /* If can't view assigned changes this */ - if (in_array('can_view_unassigned',$myuser['features'])) - { - $sql_where = ""; - } - else - { - $sql_where = " , `notify_new_unassigned`='0', `notify_reply_unassigned`='0' "; - } + /* Only active users can be assigned tickets */ + if ($myuser['active']) { + /* If can't view assigned changes this */ + if (in_array('can_view_unassigned', $myuser['features'])) { + $sql_where = ""; + } else { + $sql_where = " , `notify_new_unassigned`='0', `notify_reply_unassigned`='0' "; + } + } else { + $myuser['autoassign'] = 0; + $sql_where = " , `notify_new_unassigned`='0', `notify_new_my`='0', `notify_reply_unassigned`='0', `notify_reply_my`='0', `notify_assigned`='0', `notify_pm`='0', `notify_note`='0' "; + } /* Check for duplicate usernames */ $res = hesk_dbQuery("SELECT `id`,`isadmin`,`categories`,`heskprivileges` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."users` WHERE `user` = '".hesk_dbEscape($myuser['user'])."' LIMIT 1"); @@ -878,6 +881,7 @@ function update_user() `signature`='".hesk_dbEscape($myuser['signature'])."'," . ( isset($myuser['pass']) ? "`pass`='".hesk_dbEscape($myuser['pass'])."'," : '' ) . " `categories`='".hesk_dbEscape($myuser['categories'])."', `isadmin`='".intval($myuser['isadmin'])."', + `active`='".intval($myuser['active'])."', `autoassign`='".intval($myuser['autoassign'])."', `heskprivileges`='".hesk_dbEscape($myuser['features'])."', `can_manage_settings`='".hesk_dbEscape($myuser['can_manage_settings'])."' @@ -904,6 +908,7 @@ function hesk_validateUserInfo($pass_required = 1, $redirect_to = './manage_user $myuser['can_manage_settings'] = isset($_POST['manage_settings']) ? 1 : 0; $myuser['signature'] = hesk_input( hesk_POST('signature') ); $myuser['autoassign'] = hesk_POST('autoassign') == 'Y' ? 1 : 0; + $myuser['active'] = empty($_POST['active']) ? 0 : 1; /* If it's not admin at least one category and fature is required */ $myuser['categories'] = array(); @@ -1082,7 +1087,6 @@ function toggle_active() $active = 0; $tmp = $hesklang['user_deactivated']; } - hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."users` SET `active` = '".$active."' WHERE `id` = '".intval($myuser)."'"); if (hesk_dbAffectedRows() != 1) { From c72c5054f05db6ddfe299c86ff1f15d9b1006f04 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Fri, 24 Oct 2014 23:40:15 -0400 Subject: [PATCH 101/208] #59 Contentified some text --- language/en/text.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/language/en/text.php b/language/en/text.php index 83c1c762..5332e761 100644 --- a/language/en/text.php +++ b/language/en/text.php @@ -26,6 +26,11 @@ $hesklang['display_rtl'] = 'Display site right-to-left'; $hesklang['show_icons_navigation'] = 'Show icons on navigation bar'; $hesklang['enable_maintenance'] = 'Enable maintenance mode'; $hesklang['can_man_settings']='Can manage help desk settings'; +$hesklang['disable_user'] = 'User is active (click to deactivate)'; +$hesklang['enable_user'] = 'User is inactive (click to activate)'; +$hesklang['user_activated'] = 'User has been activated'; +$hesklang['user_deactivated'] = 'User has been deactivated'; +$hesklang['active_user'] = 'Is active user'; // ADDED OR MODIFIED IN NuMods 1.4.0 $hesklang['numods'] = 'NuMods'; From ddd1a05f65ff6d27fa3c17a947f300482904eb40 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Fri, 24 Oct 2014 23:43:10 -0400 Subject: [PATCH 102/208] #59 Don't allow users to deactivate themselves --- admin/manage_users.php | 6 ++++++ language/en/text.php | 1 + 2 files changed, 7 insertions(+) diff --git a/admin/manage_users.php b/admin/manage_users.php index dd281e22..fc93703d 100644 --- a/admin/manage_users.php +++ b/admin/manage_users.php @@ -1078,6 +1078,12 @@ function toggle_active() $myuser = intval(hesk_GET('id')) or hesk_error($hesklang['no_valid_id']); $_SESSION['seluser'] = $myuser; + if (intval($myuser) == $_SESSION['id']) + { + //-- You can't deactivate yourself! + hesk_process_messages($hesklang['self_deactivation'], './manage_users.php'); + } + if (intval(hesk_GET('s'))) { $active = 1; diff --git a/language/en/text.php b/language/en/text.php index 5332e761..36422382 100644 --- a/language/en/text.php +++ b/language/en/text.php @@ -31,6 +31,7 @@ $hesklang['enable_user'] = 'User is inactive (click to activate)'; $hesklang['user_activated'] = 'User has been activated'; $hesklang['user_deactivated'] = 'User has been deactivated'; $hesklang['active_user'] = 'Is active user'; +$hesklang['self_deactivation'] = 'You cannot deactivate yourself!'; // ADDED OR MODIFIED IN NuMods 1.4.0 $hesklang['numods'] = 'NuMods'; From 9c6436a27d3230cc5795b52b542057d67162e8b4 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Fri, 24 Oct 2014 23:46:03 -0400 Subject: [PATCH 103/208] #59 Don't show the deactivate icon for the current user --- admin/manage_users.php | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/admin/manage_users.php b/admin/manage_users.php index fc93703d..30818572 100644 --- a/admin/manage_users.php +++ b/admin/manage_users.php @@ -429,11 +429,14 @@ while ($myuser = hesk_dbFetchAssoc($res)) $autoassign_code = ''; } - /* Is the user active? */ - if ($myuser['active']) { - $activeMarkup = ''; - } else { - $activeMarkup = ''; + $activeMarkup = ''; + if ($myuser['id'] != $_SESSION['id']) { + /* Is the user active? */ + if ($myuser['active']) { + $activeMarkup = ''; + } else { + $activeMarkup = ''; + } } echo << Date: Fri, 24 Oct 2014 23:47:07 -0400 Subject: [PATCH 104/208] #59 Only pull back active users --- admin/new_ticket.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/new_ticket.php b/admin/new_ticket.php index 0c140113..e6ff91ae 100644 --- a/admin/new_ticket.php +++ b/admin/new_ticket.php @@ -61,7 +61,7 @@ if (!isset($_SESSION['isnotice'])) /* List of users */ $admins = array(); -$result = hesk_dbQuery("SELECT `id`,`name`,`isadmin`,`categories`,`heskprivileges` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."users` ORDER BY `id` ASC"); +$result = hesk_dbQuery("SELECT `id`,`name`,`isadmin`,`categories`,`heskprivileges` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."users` WHERE `active` = '1' ORDER BY `id` ASC"); while ($row=hesk_dbFetchAssoc($result)) { /* Is this an administrator? */ From c4a50d10f72673355d92251083f4fcfe05ebeea3 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Fri, 24 Oct 2014 23:55:29 -0400 Subject: [PATCH 105/208] Missed some content --- language/en/text.php | 1 + 1 file changed, 1 insertion(+) diff --git a/language/en/text.php b/language/en/text.php index 36422382..b2373a17 100644 --- a/language/en/text.php +++ b/language/en/text.php @@ -32,6 +32,7 @@ $hesklang['user_activated'] = 'User has been activated'; $hesklang['user_deactivated'] = 'User has been deactivated'; $hesklang['active_user'] = 'Is active user'; $hesklang['self_deactivation'] = 'You cannot deactivate yourself!'; +$hesklang['inactive_user'] = 'Your account is currently inactive. Contact an administrator for more information.'; // ADDED OR MODIFIED IN NuMods 1.4.0 $hesklang['numods'] = 'NuMods'; From de6136bf2640da4892c0c33fdb469a421d3a0667 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Fri, 24 Oct 2014 23:59:49 -0400 Subject: [PATCH 106/208] Fixed some SQL statements --- install/updateTo1-5-0.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/install/updateTo1-5-0.php b/install/updateTo1-5-0.php index 8be6bf80..3d531523 100644 --- a/install/updateTo1-5-0.php +++ b/install/updateTo1-5-0.php @@ -4,9 +4,8 @@ define('HESK_PATH','../'); require(HESK_PATH . 'install/install_functions.inc.php'); require(HESK_PATH . 'hesk_settings.inc.php'); hesk_dbConnect(); -hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."users` ADD COLUMN `active` ENUM('0', '1') NOT NULL DEFAULT 1 AFTER `autorefresh`"); -hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."users` SET `active` = 1"); -hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."users` ADD COLUMN `can_manage_settings` ENUM('0', '1') NOT NULL DEFAULT 1"); +hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."users` ADD COLUMN `active` ENUM('0', '1') NOT NULL DEFAULT '1'"); +hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."users` ADD COLUMN `can_manage_settings` ENUM('0', '1') NOT NULL DEFAULT '1'"); ?>

    Update complete!

    From 1fa8e19f9826ff13f7c2a00bbf6a1d36675426e8 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sat, 25 Oct 2014 00:06:19 -0400 Subject: [PATCH 107/208] Missed some content --- admin/profile.php | 3 +-- language/en/text.php | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/admin/profile.php b/admin/profile.php index aabac112..e784edad 100644 --- a/admin/profile.php +++ b/admin/profile.php @@ -258,9 +258,8 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
    - +
    -
    diff --git a/language/en/text.php b/language/en/text.php index b2373a17..9ec28540 100644 --- a/language/en/text.php +++ b/language/en/text.php @@ -22,6 +22,7 @@ $hesklang['_COLLATE']='utf8_unicode_ci'; $hesklang['EMAIL_HR']='------ Reply above this line ------'; // ADDED OR MODIFIED IN NuMods 1.5.0 +$hesklang['ticket_auto_refresh'] = 'Ticket Table Auto-Refresh:'; $hesklang['display_rtl'] = 'Display site right-to-left'; $hesklang['show_icons_navigation'] = 'Show icons on navigation bar'; $hesklang['enable_maintenance'] = 'Enable maintenance mode'; From 2c03c30e61deb77f6eafd3992e90afc58a26d374 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sat, 25 Oct 2014 00:14:03 -0400 Subject: [PATCH 108/208] #62 The profile page can now handle default settings for sending emails on replies --- admin/profile.php | 12 +++++++++++- language/en/text.php | 2 ++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/admin/profile.php b/admin/profile.php index e784edad..aea18c18 100644 --- a/admin/profile.php +++ b/admin/profile.php @@ -256,6 +256,14 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
    +
    + +
    +
    + +
    +
    +
    @@ -412,6 +420,7 @@ function update_profile() { $_SESSION['new']['notify_assigned'] = empty($_POST['notify_assigned']) ? 0 : 1; $_SESSION['new']['notify_note'] = empty($_POST['notify_note']) ? 0 : 1; $_SESSION['new']['notify_pm'] = empty($_POST['notify_pm']) ? 0 : 1; + $_SESSION['new']['default_notify_customer_email'] = empty($_POST['default_notify_customer_email']) ? 0 : 1; /* Any errors? */ if (strlen($hesk_error_buffer)) @@ -441,7 +450,8 @@ function update_profile() { `notify_reply_my`='".intval($_SESSION['new']['notify_reply_my'])."' , `notify_assigned`='".intval($_SESSION['new']['notify_assigned'])."' , `notify_pm`='".intval($_SESSION['new']['notify_pm'])."', - `notify_note`='".intval($_SESSION['new']['notify_note'])."' + `notify_note`='".intval($_SESSION['new']['notify_note'])."', + `default_notify_customer_email`='".intval($_SESSION['new']['default_notify_customer_email'])."' WHERE `id`='".intval($_SESSION['id'])."' LIMIT 1" ); diff --git a/language/en/text.php b/language/en/text.php index 9ec28540..e1824e3e 100644 --- a/language/en/text.php +++ b/language/en/text.php @@ -34,6 +34,8 @@ $hesklang['user_deactivated'] = 'User has been deactivated'; $hesklang['active_user'] = 'Is active user'; $hesklang['self_deactivation'] = 'You cannot deactivate yourself!'; $hesklang['inactive_user'] = 'Your account is currently inactive. Contact an administrator for more information.'; +$hesklang['notify_customer_email'] = 'Emails to customer on reply'; +$hesklang['notify_customer_email_text'] = 'Don\'t send email notifications of replies to the customer by default'; // ADDED OR MODIFIED IN NuMods 1.4.0 $hesklang['numods'] = 'NuMods'; From 7c40c25cff780054fbbf3ddb48b6c3a5e09e338f Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sat, 25 Oct 2014 00:14:15 -0400 Subject: [PATCH 109/208] #62 The send email property should be set to false by default --- install/updateTo1-5-0.php | 1 + 1 file changed, 1 insertion(+) diff --git a/install/updateTo1-5-0.php b/install/updateTo1-5-0.php index 3d531523..06cb8f95 100644 --- a/install/updateTo1-5-0.php +++ b/install/updateTo1-5-0.php @@ -6,6 +6,7 @@ require(HESK_PATH . 'hesk_settings.inc.php'); hesk_dbConnect(); hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."users` ADD COLUMN `active` ENUM('0', '1') NOT NULL DEFAULT '1'"); hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."users` ADD COLUMN `can_manage_settings` ENUM('0', '1') NOT NULL DEFAULT '1'"); +hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."users` ADD COLUMN `default_notify_customer_email` ENUM ('0', '1') NOT NULL DEFAULT '0'"); ?>

    Update complete!

    From 95c89c612a05ac45f5e5531d5e755671763e1d5c Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sat, 25 Oct 2014 00:19:20 -0400 Subject: [PATCH 110/208] #62 Ticket screen now honors the email profile setting --- admin/admin_ticket.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/admin/admin_ticket.php b/admin/admin_ticket.php index 1099df52..43dd997c 100644 --- a/admin/admin_ticket.php +++ b/admin/admin_ticket.php @@ -1360,10 +1360,12 @@ function hesk_printReplyForm() {

    ()
    -

    - '; - } ?> + +

    + + +

    + From eff111e58309c0c5da3968325a108258e22fd24e Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sat, 25 Oct 2014 00:25:43 -0400 Subject: [PATCH 111/208] #62 The DB should treat a 1 as "notify the customer", not 0 --- admin/admin_ticket.php | 2 +- admin/profile.php | 4 ++-- install/updateTo1-5-0.php | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/admin/admin_ticket.php b/admin/admin_ticket.php index 43dd997c..6097bbf7 100644 --- a/admin/admin_ticket.php +++ b/admin/admin_ticket.php @@ -1364,7 +1364,7 @@ function hesk_printReplyForm() {

    -

    +

    diff --git a/admin/profile.php b/admin/profile.php index aea18c18..7fad65db 100644 --- a/admin/profile.php +++ b/admin/profile.php @@ -260,7 +260,7 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
    - +
    @@ -420,7 +420,7 @@ function update_profile() { $_SESSION['new']['notify_assigned'] = empty($_POST['notify_assigned']) ? 0 : 1; $_SESSION['new']['notify_note'] = empty($_POST['notify_note']) ? 0 : 1; $_SESSION['new']['notify_pm'] = empty($_POST['notify_pm']) ? 0 : 1; - $_SESSION['new']['default_notify_customer_email'] = empty($_POST['default_notify_customer_email']) ? 0 : 1; + $_SESSION['new']['default_notify_customer_email'] = empty($_POST['default_notify_customer_email']) ? 1 : 0; /* Any errors? */ if (strlen($hesk_error_buffer)) diff --git a/install/updateTo1-5-0.php b/install/updateTo1-5-0.php index 06cb8f95..b283807a 100644 --- a/install/updateTo1-5-0.php +++ b/install/updateTo1-5-0.php @@ -6,7 +6,7 @@ require(HESK_PATH . 'hesk_settings.inc.php'); hesk_dbConnect(); hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."users` ADD COLUMN `active` ENUM('0', '1') NOT NULL DEFAULT '1'"); hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."users` ADD COLUMN `can_manage_settings` ENUM('0', '1') NOT NULL DEFAULT '1'"); -hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."users` ADD COLUMN `default_notify_customer_email` ENUM ('0', '1') NOT NULL DEFAULT '0'"); +hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."users` ADD COLUMN `default_notify_customer_email` ENUM ('0', '1') NOT NULL DEFAULT '1'"); ?>

    Update complete!

    From a45d97a9db8477b5211cfa13b78bf84d992c50eb Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 26 Oct 2014 11:19:01 -0400 Subject: [PATCH 112/208] Closes #65: The god admin cannot be edited by other users --- admin/manage_users.php | 11 +++++++++-- language/en/text.php | 1 + 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/admin/manage_users.php b/admin/manage_users.php index 30818572..30e2c619 100644 --- a/admin/manage_users.php +++ b/admin/manage_users.php @@ -387,8 +387,10 @@ while ($myuser = hesk_dbFetchAssoc($res)) if ($myuser['id'] == $_SESSION['id']) { $edit_code = ''; - } - else + } elseif ($myuser['id'] == 1) + { + $edit_code = ' '; + } else { $edit_code = ''; } @@ -541,6 +543,11 @@ function edit_user() hesk_process_messages($hesklang['eyou'],'profile.php','NOTICE'); } + if ($id == 1) + { + hesk_process_messages($hesklang['cant_edit_admin'],'./manage_users.php'); + } + $_SESSION['edit_userdata'] = TRUE; if ( ! isset($_SESSION['save_userdata'])) diff --git a/language/en/text.php b/language/en/text.php index e1824e3e..23eb6d45 100644 --- a/language/en/text.php +++ b/language/en/text.php @@ -36,6 +36,7 @@ $hesklang['self_deactivation'] = 'You cannot deactivate yourself!'; $hesklang['inactive_user'] = 'Your account is currently inactive. Contact an administrator for more information.'; $hesklang['notify_customer_email'] = 'Emails to customer on reply'; $hesklang['notify_customer_email_text'] = 'Don\'t send email notifications of replies to the customer by default'; +$hesklang['cant_edit_admin'] = 'You cannot edit the God Admin (User ID = 1)'; // ADDED OR MODIFIED IN NuMods 1.4.0 $hesklang['numods'] = 'NuMods'; From ef5e75696ae550fd1746b6193f2a962d4d01764b Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 26 Oct 2014 14:58:05 -0400 Subject: [PATCH 113/208] #57 Finished UI portion of customer category specification feature --- admin/admin_settings.php | 24 ++++++++++++++++++++++++ admin/admin_settings_save.php | 5 +++++ language/en/text.php | 4 ++++ nuMods_settings.inc.php | 3 +++ 4 files changed, 36 insertions(+) diff --git a/admin/admin_settings.php b/admin/admin_settings.php index 6a4e52bd..ff6d1ea0 100644 --- a/admin/admin_settings.php +++ b/admin/admin_settings.php @@ -1831,6 +1831,30 @@ if ( defined('HESK_DEMO') ) +
    + +
    +
    + +
       +
    + +
       +
    + +
    +
    +
    diff --git a/admin/admin_settings_save.php b/admin/admin_settings_save.php index 8ee0d3c2..61272ef8 100644 --- a/admin/admin_settings_save.php +++ b/admin/admin_settings_save.php @@ -401,6 +401,7 @@ for ($i=1;$i<=20;$i++) } } + //-- Update the statuses hesk_dbConnect(); $wasStatusDeleted = false; @@ -550,6 +551,7 @@ $set['dropdownItemTextColor'] = hesk_input(hesk_POST('dropdownItemTextColor')); $set['dropdownItemTextHoverColor'] = hesk_input(hesk_POST('dropdownItemTextHoverColor')); $set['questionMarkColor'] = hesk_input(hesk_POST('questionMarkColor')); $set['dropdownItemTextHoverBackgroundColor'] = hesk_input(hesk_POST('dropdownItemTextHoverBackgroundColor')); +$set['customer-category'] = hesk_input(hesk_POST('customer-category')); $nuMods_file_content=' Date: Sun, 26 Oct 2014 20:48:07 -0400 Subject: [PATCH 114/208] Revert "#57 Finished UI portion of customer category specification feature" This reverts commit ef5e75696ae550fd1746b6193f2a962d4d01764b. --- admin/admin_settings.php | 24 ------------------------ admin/admin_settings_save.php | 5 ----- language/en/text.php | 4 ---- nuMods_settings.inc.php | 3 --- 4 files changed, 36 deletions(-) diff --git a/admin/admin_settings.php b/admin/admin_settings.php index ff6d1ea0..6a4e52bd 100644 --- a/admin/admin_settings.php +++ b/admin/admin_settings.php @@ -1831,30 +1831,6 @@ if ( defined('HESK_DEMO') )
    -
    - -
    -
    - -
       -
    - -
       -
    - -
    -
    -
    diff --git a/admin/admin_settings_save.php b/admin/admin_settings_save.php index 61272ef8..8ee0d3c2 100644 --- a/admin/admin_settings_save.php +++ b/admin/admin_settings_save.php @@ -401,7 +401,6 @@ for ($i=1;$i<=20;$i++) } } - //-- Update the statuses hesk_dbConnect(); $wasStatusDeleted = false; @@ -551,7 +550,6 @@ $set['dropdownItemTextColor'] = hesk_input(hesk_POST('dropdownItemTextColor')); $set['dropdownItemTextHoverColor'] = hesk_input(hesk_POST('dropdownItemTextHoverColor')); $set['questionMarkColor'] = hesk_input(hesk_POST('questionMarkColor')); $set['dropdownItemTextHoverBackgroundColor'] = hesk_input(hesk_POST('dropdownItemTextHoverBackgroundColor')); -$set['customer-category'] = hesk_input(hesk_POST('customer-category')); $nuMods_file_content=' Date: Sun, 26 Oct 2014 21:18:21 -0400 Subject: [PATCH 115/208] Closes #75: Current user cannot be deleted, and god admin can't be disabled --- admin/manage_users.php | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/admin/manage_users.php b/admin/manage_users.php index 30e2c619..cdce6e1d 100644 --- a/admin/manage_users.php +++ b/admin/manage_users.php @@ -404,12 +404,11 @@ while ($myuser = hesk_dbFetchAssoc($res)) $myuser['isadmin'] = ''.$hesklang['no'].''; } - /* Deleting user with ID 1 (default administrator) is not allowed */ - if ($myuser['id'] == 1) + /* Deleting user with ID 1 (default administrator) is not allowed. Also don't allow the logged in user to be deleted or inactivated */ + if ($myuser['id'] == 1 || $myuser['id'] == $_SESSION['id']) { $remove_code = ' '; - } - else + } else { $remove_code = ' '; } @@ -432,7 +431,7 @@ while ($myuser = hesk_dbFetchAssoc($res)) } $activeMarkup = ''; - if ($myuser['id'] != $_SESSION['id']) { + if ($myuser['id'] != $_SESSION['id'] && $myuser['id'] != 1) { /* Is the user active? */ if ($myuser['active']) { $activeMarkup = ''; From 86393193f4f0c56997711927b092cbf7cf223f30 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 26 Oct 2014 21:46:49 -0400 Subject: [PATCH 116/208] Updated version number --- README.md | 5 +++-- install/install_functions.inc.php | 2 +- install/updateNuMods.php | 2 +- nuMods_settings.inc.php | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 5b5def5a..3ee2c5e6 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ [![Stories in Ready](https://badge.waffle.io/mkoch227/numods.png?label=ready&title=Ready)](https://waffle.io/mkoch227/numods) -

    NuMods v1.4.1

    +

    NuMods v1.5.0

    This branch contains all files modified from the base version of HESK to become NuMods, a set of modifications for HESK v2.x @@ -13,11 +13,12 @@ This branch contains all files modified from the base version of HESK to become
  • Dynamically add columns to the ticket dashboard
  • Maintenance Mode
  • Ticket Dashboard Automatic Refresh
  • +
  • ...and more!
  • Download

    -You can download this tweak via two ways: +You can download this mod via two ways:
    1. Stable Releases: Releases that have a release tag associated with a commit are considered releases. You can click on "releases" on the top of the repo, and then click "zip" or "tar.gz" to download the repo at that stage.
    2. diff --git a/install/install_functions.inc.php b/install/install_functions.inc.php index 78ba56f7..41d56f46 100644 --- a/install/install_functions.inc.php +++ b/install/install_functions.inc.php @@ -37,7 +37,7 @@ if (!defined('IN_SCRIPT')) {die('Invalid attempt');} // We will be installing this HESK version: define('HESK_NEW_VERSION','2.5.5'); -define('NUMODS_NEW_VERSION','1.4.1'); +define('NUMODS_NEW_VERSION','1.5.0'); // Other required files and settings define('INSTALL',1); diff --git a/install/updateNuMods.php b/install/updateNuMods.php index a2d8e2b8..f57e14ce 100644 --- a/install/updateNuMods.php +++ b/install/updateNuMods.php @@ -74,7 +74,7 @@ if ($_GET['update'] == 1)

      Update NuMods from v1.4.1 to v1.5.0

      -

      Update here. Do not use the installation below!

      +

      Update here. Do not use the installation below!

      Update NuMods from v1.2.4 - v1.3.0 to v1.5.0

      If you attempted the v1.4.0 installation and it failed, use this update link. Do not use the link below!

      Update here. Do not use the installation below!

      diff --git a/nuMods_settings.inc.php b/nuMods_settings.inc.php index d5e88f84..e7053cf9 100644 --- a/nuMods_settings.inc.php +++ b/nuMods_settings.inc.php @@ -23,4 +23,4 @@ $nuMods_settings['show_icons'] = 0; $nuMods_settings['maintenance_mode'] = 0; /* DO NOT EDIT ANYTHING BELOW THIS LINE */ -$nuMods_settings['version']= '1.4.1'; \ No newline at end of file +$nuMods_settings['version']= '1.5.0'; \ No newline at end of file From aa2e74a92aac5045c0d9a388d78a86722a1c54f9 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 2 Nov 2014 10:45:35 -0500 Subject: [PATCH 117/208] Closes #79: Added missing SQL statement in update script --- install/updateNuMods.php | 1 + 1 file changed, 1 insertion(+) diff --git a/install/updateNuMods.php b/install/updateNuMods.php index f57e14ce..8cbaf2f2 100644 --- a/install/updateNuMods.php +++ b/install/updateNuMods.php @@ -63,6 +63,7 @@ if ($_GET['update'] == 1) hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` ADD COLUMN `parent` MEDIUMINT(8) NULL AFTER `custom20`;"); hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."users` ADD COLUMN `active` BIT NOT NULL DEFAULT 1 AFTER `autorefresh`"); hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."users` ADD COLUMN `can_manage_settings` INT NOT NULL DEFAULT 1"); + hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."users` ADD COLUMN `default_notify_customer_email` ENUM ('0', '1') NOT NULL DEFAULT '1'"); } } From e535f2fb4ea17febe51bcdd4466de34df66a1212 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Thu, 6 Nov 2014 09:24:51 -0500 Subject: [PATCH 118/208] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 3ee2c5e6..31e75c16 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ -[![Stories in Ready](https://badge.waffle.io/mkoch227/numods.png?label=ready&title=Ready)](https://waffle.io/mkoch227/numods) +[![Stories in Ready](https://badge.waffle.io/mkoch227/Mods-For-Hesk.png?label=ready&title=Ready)](https://waffle.io/mkoch227/Mods-For-Hesk) +[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/mkoch227/mods-for-hesk/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

      NuMods v1.5.0

      This branch contains all files modified from the base version of HESK to become NuMods, a set of modifications for HESK v2.x From ade760b3b312918c8e3d50ad3b82dfa0658954df Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Mon, 17 Nov 2014 23:55:56 -0500 Subject: [PATCH 119/208] Closes #82 The active flag is an enum value (string), not an integer --- admin/admin_ticket.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/admin_ticket.php b/admin/admin_ticket.php index 6097bbf7..7f0b7398 100644 --- a/admin/admin_ticket.php +++ b/admin/admin_ticket.php @@ -419,7 +419,7 @@ while ($row=hesk_dbFetchAssoc($result)) /* List of users */ $admins = array(); -$result = hesk_dbQuery("SELECT `id`,`name`,`isadmin`,`categories`,`heskprivileges` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."users` WHERE `active` = 1 ORDER BY `id` ASC"); +$result = hesk_dbQuery("SELECT `id`,`name`,`isadmin`,`categories`,`heskprivileges` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."users` WHERE `active` = '1' ORDER BY `id` ASC"); while ($row=hesk_dbFetchAssoc($result)) { /* Is this an administrator? */ From fabb910cfd14eff7e44c3f4f4fcc9acf0d4c6e61 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Mon, 17 Nov 2014 23:58:48 -0500 Subject: [PATCH 120/208] Closes #78 Fix layout for ticket w/out customer priority showing --- ticket.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ticket.php b/ticket.php index 31777aa2..fe6cc0a5 100644 --- a/ticket.php +++ b/ticket.php @@ -294,7 +294,7 @@ require_once(HESK_PATH . 'inc/header.inc.php'); } else { - $hesk_settings['ticketColumnWidth'] = 3; + $repliesColumnWidth = 3; } echo '

      '.$hesklang['status'].'

      '; $ticketStatusKey = $ticket['statusKey']; From 20760987b772d70b2acbb2c2a1619830ba286847 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Tue, 18 Nov 2014 00:00:06 -0500 Subject: [PATCH 121/208] Closes #77 Fix print.php to properly format custom fields --- print.php | 1 + 1 file changed, 1 insertion(+) diff --git a/print.php b/print.php index c4508146..27a06a93 100644 --- a/print.php +++ b/print.php @@ -217,6 +217,7 @@ foreach ($hesk_settings['custom_fields'] as $k=>$v)
    Date: Tue, 18 Nov 2014 00:00:28 -0500 Subject: [PATCH 122/208] Added __latest.txt to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index aff7c4f2..f3ca7bf6 100644 --- a/.gitignore +++ b/.gitignore @@ -268,3 +268,4 @@ rate.php readme.html robots.txt .idea/ +attachments/__latest.txt From 473f0f905ceb082da769725de7f5c3e47dd0c5f7 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Fri, 21 Nov 2014 00:00:17 -0500 Subject: [PATCH 123/208] #72 Condensed the height of the green bar for staff --- admin/admin_ticket.php | 85 ++++++++++++++++++---------------------- css/hesk_newStyle.php | 4 +- css/hesk_newStyleRTL.php | 4 +- 3 files changed, 43 insertions(+), 50 deletions(-) diff --git a/admin/admin_ticket.php b/admin/admin_ticket.php index 7f0b7398..d0e2eb6e 100644 --- a/admin/admin_ticket.php +++ b/admin/admin_ticket.php @@ -413,8 +413,9 @@ $result = hesk_dbQuery("SELECT `id`,`name` FROM `".hesk_dbEscape($hesk_settings[ $categories_options=''; while ($row=hesk_dbFetchAssoc($result)) { - if ($row['id'] == $ticket['category']) {continue;} - $categories_options.=''; + $selected = ''; + if ($row['id'] == $ticket['category']) {$selected='selected';} + $categories_options.=''; } /* List of users */ @@ -674,12 +675,17 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
    '', - 1 => '', - 2 => '', - 3 => '' + $priorityLanguages = array( + 0 => $hesklang['critical'], + 1 => $hesklang['high'], + 2 => $hesklang['medium'], + 3 => $hesklang['low'] ); + $options = array(); + for ($i = 0; $i < 4; $i++) { + $selected = $ticket['priority'] == $i ? 'selected' : ''; + array_push($options, ''); + } echo '
    ';} @@ -688,17 +694,10 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php'); echo '

    '.$hesklang['priority'].'

    '; - if ($ticket['priority']==0) {echo '

    '.$hesklang['critical'].'

    ';} - elseif ($ticket['priority']==1) {echo '

    '.$hesklang['high'].'

    ';} - elseif ($ticket['priority']==2) {echo '

    '.$hesklang['medium'].'

    ';} - else {echo '

    '.$hesklang['low'].'

    ';} - echo '
    -
    + echo ' - '; echo implode('',$options); echo ' @@ -716,17 +715,14 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php'); $results = hesk_dbQuery("SELECT `ID`, `ShortNameContentKey` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."statuses`"); while ($row = $results->fetch_assoc()) { - $status_options[$row['ID']] = ''; + $selected = $ticket['status'] == $row['ID'] ? 'selected' : ''; + $status_options[$row['ID']] = ''; } - $ticketStatus = hesk_dbFetchAssoc(hesk_dbQuery("SELECT `TicketViewContentKey` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."statuses` WHERE ID = " .$ticket['status'])); - echo '

    '.$hesklang[$ticketStatus['TicketViewContentKey']].'

    '; - echo '
    - + echo ' @@ -735,53 +731,47 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
    '; - echo '

    '.$hesklang['owner'].'

    -

    '; - - echo isset($admins[$ticket['owner']]) ? $admins[$ticket['owner']] : - ($can_assign_self ? $hesklang['unas'].' ['.$hesklang['asss'].']' : $hesklang['unas']); - - echo '


    '; + echo '

    '.$hesklang['owner'].'

    '; if (hesk_checkPermission('can_assign_others',0)) { echo'
    - '; + $selectedForUnassign = 'selected'; foreach ($admins as $k=>$v) { - if ($k != $ticket['owner']) - { - echo ''; + $selected = ''; + if ($k == $ticket['owner']) { + $selectedForUnassign = ''; + $selected = 'selected'; } + echo ''; } + echo ''; echo ' '; + } else + { + echo '

    '; + echo isset($admins[$ticket['owner']]) ? $admins[$ticket['owner']] : + ($can_assign_self ? $hesklang['unas'].' ['.$hesklang['asss'].']' : $hesklang['unas']); + echo '

    '; } echo '
    '; - echo '

    '.$hesklang['category'].'

    -

    '.$category['name'].'

    '; - + echo '

    '.$hesklang['category'].'

    '; if ($can_change_cat) { echo ' -
    @@ -789,8 +779,11 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php'); - '; } - + '; + } else + { + echo '

    '.$category['name'].'

    '; + } echo '
    '; ?>
    diff --git a/css/hesk_newStyle.php b/css/hesk_newStyle.php index c7b2ac21..ff1d07ac 100644 --- a/css/hesk_newStyle.php +++ b/css/hesk_newStyle.php @@ -56,7 +56,7 @@ border-bottom: solid 1px #ddd; border-right: 0; padding-top: 5px; - height: 125px; + height: 100px; } } @@ -75,7 +75,7 @@ border-bottom: 0; border-right: solid 1px #ddd; margin-top: 1px; - height: 125px; + height: 100px; padding-top: 10px; } } diff --git a/css/hesk_newStyleRTL.php b/css/hesk_newStyleRTL.php index add02908..de5b17db 100644 --- a/css/hesk_newStyleRTL.php +++ b/css/hesk_newStyleRTL.php @@ -56,7 +56,7 @@ border-bottom: solid 1px #ddd; border-left: 0; padding-top: 5px; - height: 125px; + height: 100px; } } @@ -75,7 +75,7 @@ border-bottom: 0; border-left: solid 1px #ddd; margin-top: 1px; - height: 125px; + height: 100px; padding-top: 10px; } } From f1f62cbe3cb8033062e5a0117bca7cca78935c5a Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sat, 22 Nov 2014 20:53:18 -0500 Subject: [PATCH 124/208] Closes #72: Condense height of green bar for customer --- css/hesk_newStyle.php | 18 +++++++++++++++++- css/hesk_newStyleRTL.php | 14 +++++++++++++- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/css/hesk_newStyle.php b/css/hesk_newStyle.php index ff1d07ac..32ef5dd1 100644 --- a/css/hesk_newStyle.php +++ b/css/hesk_newStyle.php @@ -65,7 +65,7 @@ border-bottom: 0; border-right: solid 1px #ddd; margin-top: 1px; - height: 90px; + min-height: 70px; padding-top: 10px; } } @@ -207,11 +207,27 @@ font-size: 11px; text-transform: uppercase; } + +@media (min-width: 992px) { + .ticketPropertyText { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + .ticketPropertyText:hover { + white-space: normal; + overflow: none; + } +} + .ticketPropertyText { font-size: 16px; line-height: 1em; color: #fff; + padding-bottom: 2px; } + .criticalPriority { background-color: red; } diff --git a/css/hesk_newStyleRTL.php b/css/hesk_newStyleRTL.php index de5b17db..0abbd51d 100644 --- a/css/hesk_newStyleRTL.php +++ b/css/hesk_newStyleRTL.php @@ -65,7 +65,7 @@ border-bottom: 0; border-left: solid 1px #ddd; margin-top: 1px; - height: 90px; + min-height: 70px; padding-top: 10px; } } @@ -210,6 +210,18 @@ font-size: 11px; text-transform: uppercase; } +@media (min-width: 992px) { + .ticketPropertyText { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + .ticketPropertyText:hover { + white-space: normal; + overflow: none; + } +} .ticketPropertyText { font-size: 16px; line-height: 1em; From 83b4b16d4844b01bdaf54d823ca7720dbe9baf27 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 23 Nov 2014 00:20:28 -0500 Subject: [PATCH 125/208] Closes #73: Send email to customer when ticket closed --- .gitignore | 3 - admin/change_status.php | 21 + admin/delete_tickets.php | 292 +++++++++++ inc/admin_functions.inc.php | 694 +++++++++++++++++++++++++++ inc/email_functions.inc.php | 617 ++++++++++++++++++++++++ language/en/emails/ticket_closed.txt | 14 + language/en/text.php | 5 + 7 files changed, 1643 insertions(+), 3 deletions(-) create mode 100644 admin/delete_tickets.php create mode 100644 inc/admin_functions.inc.php create mode 100644 inc/email_functions.inc.php create mode 100644 language/en/emails/ticket_closed.txt diff --git a/.gitignore b/.gitignore index f3ca7bf6..fd26d961 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,6 @@ admin/admin_suggest_articles.php admin/archive.php admin/assign_owner.php -admin/delete_tickets.php admin/generate_spam_question.php admin/move_category.php admin/options.php @@ -149,7 +148,6 @@ img/tag_off.png img/unlock.png img/vertical.jpg img/view.png -inc/admin_functions.inc.php inc/assignment_search.inc.php inc/attachments.inc.php inc/calendar/img/cal.gif @@ -164,7 +162,6 @@ inc/calendar/tcal.js inc/calendar/tcal.php inc/database.inc.php inc/database_mysqli.inc.php -inc/email_functions.inc.php inc/footer.inc.php inc/index.htm inc/mail/email_parser.php diff --git a/admin/change_status.php b/admin/change_status.php index 1b594d74..890e61c2 100644 --- a/admin/change_status.php +++ b/admin/change_status.php @@ -74,6 +74,13 @@ if ( ! isset($status_options[$status])) $locked = 0; +// Ticket info +$result = hesk_dbQuery("SELECT * FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` WHERE `trackid`='".hesk_dbEscape($trackingID)."' LIMIT 1"); +if (hesk_dbNumRows($result) != 1) { + hesk_error($hesklang['ticket_not_found']); +} +$ticket = hesk_dbFetchAssoc($result); + $statusRow = hesk_dbFetchAssoc(hesk_dbQuery("SELECT `ID`, `IsClosed` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."statuses` WHERE ID = ".$status)); if ($statusRow['IsClosed']) // Closed { @@ -84,6 +91,10 @@ if ($statusRow['IsClosed']) // Closed { $locked = 1; } + + // Notify customer + require(HESK_PATH . 'inc/email_functions.inc.php'); + hesk_notifyCustomer('ticket_closed'); } elseif ($statusRow['ID'] != 0) //Ticket is still open, but not new { @@ -96,6 +107,16 @@ else // Ticket is marked as "NEW" $revision = sprintf($hesklang['thist4'],hesk_date(),$_SESSION['name'].' ('.$_SESSION['user'].')'); } +//-- Notify staff after ticket re-open? +$currentStatusRS = hesk_dbQuery('SELECT * FROM `'.hesk_dbEscape($hesk_settings['db_pfix']).'statuses` WHERE `ID` = '.$ticket['status']); +$currentStatus = hesk_dbFetchAssoc($currentStatusRS); + +if (intval($currentStatus['IsClosed']) == 1 && $statusRow['IsClosed'] == 0 && $ticket['owner'] != $_SESSION['id']) { + $ticket['name'] = $_SESSION['name']; + require(HESK_PATH . 'inc/email_functions.inc.php'); + hesk_notifyAssignedStaff(false, 'ticket_reopen_assigned'); +} + hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` SET `status`='{$status}', `locked`='{$locked}', `history`=CONCAT(`history`,'".hesk_dbEscape($revision)."') WHERE `trackid`='".hesk_dbEscape($trackingID)."' LIMIT 1"); if (hesk_dbAffectedRows() != 1) diff --git a/admin/delete_tickets.php b/admin/delete_tickets.php new file mode 100644 index 00000000..c68b10d6 --- /dev/null +++ b/admin/delete_tickets.php @@ -0,0 +1,292 @@ + diff --git a/inc/admin_functions.inc.php b/inc/admin_functions.inc.php new file mode 100644 index 00000000..662ffec1 --- /dev/null +++ b/inc/admin_functions.inc.php @@ -0,0 +1,694 @@ + 59) + { + $m = floor($s / 60) + $m; + $s = intval($s % 60); + } + + /* Convert minutes to hours if 60 or more minutes */ + if ($m > 59) + { + $h = floor($m / 60) + $h; + $m = intval($m % 60); + } + + /* MySQL accepts max time value of 838:59:59 */ + if ($h > 838) + { + return '838:59:59'; + } + + /* That's it, let's send out formatted time string */ + return str_pad($h, 2, "0", STR_PAD_LEFT) . ':' . str_pad($m, 2, "0", STR_PAD_LEFT) . ':' . str_pad($s, 2, "0", STR_PAD_LEFT); + +} // END hesk_getTime(); + + +function hesk_mergeTickets($merge_these, $merge_into) +{ + global $hesk_settings, $hesklang, $hesk_db_link; + + /* Target ticket must not be in the "merge these" list */ + if ( in_array($merge_into, $merge_these) ) + { + $merge_these = array_diff($merge_these, array( $merge_into ) ); + } + + /* At least 1 ticket needs to be merged with target ticket */ + if ( count($merge_these) < 1 ) + { + $_SESSION['error'] = $hesklang['merr1']; + return false; + } + + /* Make sure target ticket exists */ + $res = hesk_dbQuery("SELECT `id`,`trackid`,`category` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` WHERE `id`='".intval($merge_into)."' LIMIT 1"); + if (hesk_dbNumRows($res) != 1) + { + $_SESSION['error'] = $hesklang['merr2']; + return false; + } + $ticket = hesk_dbFetchAssoc($res); + + /* Make sure user has access to ticket category */ + if ( ! hesk_okCategory($ticket['category'], 0) ) + { + $_SESSION['error'] = $hesklang['merr3']; + return false; + } + + /* Set some variables for later */ + $merge['attachments'] = ''; + $merge['replies'] = array(); + $merge['notes'] = array(); + $sec_worked = 0; + $history = ''; + $merged = ''; + + /* Get messages, replies, notes and attachments of tickets that will be merged */ + foreach ($merge_these as $this_id) + { + /* Validate ID */ + if ( is_array($this_id) ) + { + continue; + } + $this_id = intval($this_id) or hesk_error($hesklang['id_not_valid']); + + /* Get required ticket information */ + $res = hesk_dbQuery("SELECT `id`,`trackid`,`category`,`name`,`message`,`dt`,`time_worked`,`attachments` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` WHERE `id`='".intval($this_id)."' LIMIT 1"); + if (hesk_dbNumRows($res) != 1) + { + continue; + } + $row = hesk_dbFetchAssoc($res); + + /* Has this user access to the ticket category? */ + if ( ! hesk_okCategory($row['category'], 0) ) + { + continue; + } + + /* Insert ticket message as a new reply to target ticket */ + hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."replies` (`replyto`,`name`,`message`,`dt`,`attachments`) VALUES ('".intval($ticket['id'])."','".hesk_dbEscape($row['name'])."','".hesk_dbEscape($row['message'])."','".hesk_dbEscape($row['dt'])."','".hesk_dbEscape($row['attachments'])."')"); + + /* Update attachments */ + hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."attachments` SET `ticket_id`='".hesk_dbEscape($ticket['trackid'])."' WHERE `ticket_id`='".hesk_dbEscape($row['trackid'])."'"); + + /* Get old ticket replies and insert them as new replies */ + $res = hesk_dbQuery("SELECT * FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."replies` WHERE `replyto`='".intval($row['id'])."'"); + while ( $reply = hesk_dbFetchAssoc($res) ) + { + hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."replies` (`replyto`,`name`,`message`,`dt`,`attachments`,`staffid`,`rating`,`read`) VALUES ('".intval($ticket['id'])."','".hesk_dbEscape($reply['name'])."','".hesk_dbEscape($reply['message'])."','".hesk_dbEscape($reply['dt'])."','".hesk_dbEscape($reply['attachments'])."','".intval($reply['staffid'])."','".intval($reply['rating'])."','".intval($reply['read'])."')"); + } + + /* Delete replies to the old ticket */ + hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."replies` WHERE `replyto`='".intval($row['id'])."'"); + + /* Get old ticket notes and insert them as new notes */ + $res = hesk_dbQuery("SELECT * FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."notes` WHERE `ticket`='".intval($row['id'])."'"); + while ( $note = hesk_dbFetchAssoc($res) ) + { + hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."notes` (`ticket`,`who`,`dt`,`message`) VALUES ('".intval($ticket['id'])."','".intval($note['who'])."','".hesk_dbEscape($note['dt'])."','".hesk_dbEscape($note['message'])."')"); + } + + /* Delete replies to the old ticket */ + hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."notes` WHERE `ticket`='".intval($row['id'])."'"); + + /* Delete old ticket */ + hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` WHERE `id`='".intval($row['id'])."'"); + + /* Log that ticket has been merged */ + $history .= sprintf($hesklang['thist13'],hesk_date(),$row['trackid'],$_SESSION['name'].' ('.$_SESSION['user'].')'); + + /* Add old ticket ID to target ticket "merged" field */ + $merged .= '#' . $row['trackid']; + + /* Convert old ticket "time worked" to seconds and add to $sec_worked variable */ + list ($hr, $min, $sec) = explode(':', $row['time_worked']); + $sec_worked += (((int)$hr) * 3600) + (((int)$min) * 60) + ((int)$sec); + } + + /* Convert seconds to HHH:MM:SS */ + $sec_worked = hesk_getTime('0:'.$sec_worked); + + /* Update history (log) and merged IDs of target ticket */ + hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` SET `time_worked`=ADDTIME(`time_worked`, '".hesk_dbEscape($sec_worked)."'), `merged`=CONCAT(`merged`,'".hesk_dbEscape($merged . '#')."'), `history`=CONCAT(`history`,'".hesk_dbEscape($history)."') WHERE `id`='".intval($merge_into)."' LIMIT 1"); + + return true; + +} // END hesk_mergeTickets() + + +function hesk_updateStaffDefaults() +{ + global $hesk_settings, $hesklang; + + // Demo mode + if ( defined('HESK_DEMO') ) + { + return true; + } + // Remove the part that forces saving as default - we don't need it every time + $default_list = str_replace('&def=1','',$_SERVER['QUERY_STRING']); + + // Update database + $res = hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."users` SET `default_list`='".hesk_dbEscape($default_list)."' WHERE `id`='".intval($_SESSION['id'])."'"); + + // Update session values so the changes take effect immediately + $_SESSION['default_list'] = $default_list; + + return true; + +} // END hesk_updateStaffDefaults() + + +function hesk_makeJsString($in) +{ + return addslashes(preg_replace("/\s+/",' ',$in)); +} // END hesk_makeJsString() + + +function hesk_checkNewMail() +{ + global $hesk_settings, $hesklang; + + $res = hesk_dbQuery("SELECT COUNT(*) FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."mail` WHERE `to`='".intval($_SESSION['id'])."' AND `read`='0' AND `deletedby`!='".intval($_SESSION['id'])."' "); + $num = hesk_dbResult($res,0,0); + + return $num; +} // END hesk_checkNewMail() + + +function hesk_dateToString($dt, $returnName=1, $returnTime=0, $returnMonth=0, $from_database=false) +{ + global $hesk_settings, $hesklang; + + $dt = strtotime($dt); + + // Adjust MySQL time if different from PHP time + if ($from_database) + { + if ( ! defined('MYSQL_TIME_DIFF') ) + { + define('MYSQL_TIME_DIFF', time()-hesk_dbTime() ); + } + + if (MYSQL_TIME_DIFF != 0) + { + $dt += MYSQL_TIME_DIFF; + } + + // Add HESK set time difference + $dt += 3600*$hesk_settings['diff_hours'] + 60*$hesk_settings['diff_minutes']; + + // Daylight saving? + if ($hesk_settings['daylight'] && date('I', $dt)) + { + $dt += 3600; + } + } + + list($y,$m,$n,$d,$G,$i,$s) = explode('-', date('Y-n-j-w-G-i-s', $dt) ); + + $m = $hesklang['m'.$m]; + $d = $hesklang['d'.$d]; + + if ($returnName) + { + return "$d, $m $n, $y"; + } + + if ($returnTime) + { + return "$d, $m $n, $y $G:$i:$s"; + } + + if ($returnMonth) + { + return "$m $y"; + } + + return "$m $n, $y"; +} // End hesk_dateToString() + + +function hesk_getCategoriesArray($kb = 0) { + global $hesk_settings, $hesklang, $hesk_db_link; + + $categories = array(); + if ($kb) + { + $result = hesk_dbQuery('SELECT `id`, `name` FROM `'.hesk_dbEscape($hesk_settings['db_pfix']).'kb_categories` ORDER BY `cat_order` ASC'); + } + else + { + $result = hesk_dbQuery('SELECT `id`, `name` FROM `'.hesk_dbEscape($hesk_settings['db_pfix']).'categories` ORDER BY `cat_order` ASC'); + } + + while ($row=hesk_dbFetchAssoc($result)) + { + $categories[$row['id']] = $row['name']; + } + + return $categories; +} // END hesk_getCategoriesArray() + + +function hesk_getHTML($in) +{ + global $hesk_settings, $hesklang; + + $replace_from = array("\t","","$","<%","%>"); + $replace_to = array("","<?","?>","\$","<%","%>"); + + $in = trim($in); + $in = str_replace($replace_from,$replace_to,$in); + $in = preg_replace('/\(.*)\<\/script\>/Uis',"",$in); + $in = preg_replace('/\<\!\-\-(.*)\-\-\>/Uis',"",$in); + + if (HESK_SLASH === true) + { + $in = addslashes($in); + } + $in = str_replace('\"','"',$in); + + return $in; +} // END hesk_getHTML() + + +function hesk_autoLogin($noredirect=0) +{ + global $hesk_settings, $hesklang, $hesk_db_link; + + if (!$hesk_settings['autologin']) + { + return false; + } + + $user = hesk_htmlspecialchars( hesk_COOKIE('hesk_username') ); + $hash = hesk_htmlspecialchars( hesk_COOKIE('hesk_p') ); + define('HESK_USER', $user); + + if (empty($user) || empty($hash)) + { + return false; + } + + /* Login cookies exist, now lets limit brute force attempts */ + hesk_limitBfAttempts(); + + /* Check username */ + $result = hesk_dbQuery('SELECT * FROM `'.$hesk_settings['db_pfix']."users` WHERE `user` = '".hesk_dbEscape($user)."' LIMIT 1"); + if (hesk_dbNumRows($result) != 1) + { + setcookie('hesk_username', ''); + setcookie('hesk_p', ''); + header('Location: index.php?a=login¬ice=1'); + exit(); + } + + $res=hesk_dbFetchAssoc($result); + foreach ($res as $k=>$v) + { + $_SESSION[$k]=$v; + } + + /* Check password */ + if ($hash != hesk_Pass2Hash($_SESSION['pass'] . strtolower($user) . $_SESSION['pass']) ) + { + setcookie('hesk_username', ''); + setcookie('hesk_p', ''); + header('Location: index.php?a=login¬ice=1'); + exit(); + } + + /* Check if default password */ + if ($_SESSION['pass'] == '499d74967b28a841c98bb4baaabaad699ff3c079') + { + hesk_process_messages($hesklang['chdp'],'NOREDIRECT','NOTICE'); + } + + unset($_SESSION['pass']); + + /* Login successful, clean brute force attempts */ + hesk_cleanBfAttempts(); + + /* Regenerate session ID (security) */ + hesk_session_regenerate_id(); + + /* Get allowed categories */ + if (empty($_SESSION['isadmin'])) + { + $_SESSION['categories']=explode(',',$_SESSION['categories']); + } + + /* Renew cookies */ + setcookie('hesk_username', "$user", strtotime('+1 year')); + setcookie('hesk_p', "$hash", strtotime('+1 year')); + + /* Close any old tickets here so Cron jobs aren't necessary */ + if ($hesk_settings['autoclose']) + { + $dt = date('Y-m-d H:i:s',time() - $hesk_settings['autoclose']*86400); + + $waitingForCustomerRS = hesk_dbQuery("SELECT `ID` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."statuses` WHERE `IsDefaultStaffReplyStatus` = 1"); + $waitingForCustomerStatus = hesk_dbFetchAssoc($waitingForCustomerRS); + + $result = hesk_dbQuery("SELECT * FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` WHERE `status` = ".$waitingForCustomerStatus['ID']." AND `lastchange` <= '".hesk_dbEscape($dt)."' "); + if (hesk_dbNumRows($result) > 0) + { + require(HESK_PATH . 'inc/email_functions.inc.php'); + global $ticket; + while ($ticket = hesk_dbFetchAssoc($result)) { + hesk_notifyCustomer('ticket_closed'); + } + + $revision = sprintf($hesklang['thist3'],hesk_date(),$hesklang['auto']); + + $closedStatusRS = hesk_dbQuery("SELECT `ID` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."statuses` WHERE `IsStaffClosedOption` = 1"); + $closedStatus = hesk_dbFetchAssoc($closedStatusRS); + + $sql = "UPDATE `".$hesk_settings['db_pfix']."tickets` SET `status`=".$closedStatus['ID'].", `history`=CONCAT(`history`,'".hesk_dbEscape($revision)."') WHERE `status` = ".$waitingForCustomerStatus['ID']." AND `lastchange` <= '".hesk_dbEscape($dt)."' "; + hesk_dbQuery($sql); + } + } + + /* If session expired while a HESK page is open just continue using it, don't redirect */ + if ($noredirect) + { + return true; + } + + /* Redirect to the destination page */ + if ( hesk_isREQUEST('goto') && $url=hesk_REQUEST('goto') ) + { + $url = str_replace('&','&',$url); + header('Location: '.$url); + } + else + { + header('Location: admin_main.php'); + } + exit(); +} // END hesk_autoLogin() + + +function hesk_isLoggedIn() +{ + global $hesk_settings; + + $referer = hesk_input($_SERVER['REQUEST_URI']); + $referer = str_replace('&','&',$referer); + + if (empty($_SESSION['id'])) + { + if ($hesk_settings['autologin'] && hesk_autoLogin(1) ) + { + // Users online + if ($hesk_settings['online']) + { + require(HESK_PATH . 'inc/users_online.inc.php'); + hesk_initOnline($_SESSION['id']); + } + + return true; + } + + // Some pages cannot be redirected to + $modify_redirect = array( + 'admin_reply_ticket.php' => 'admin_main.php', + 'admin_settings_save.php' => 'admin_settings.php', + 'delete_tickets.php' => 'admin_main.php', + 'move_category.php' => 'admin_main.php', + 'priority.php' => 'admin_main.php', + ); + + foreach ($modify_redirect as $from => $to) + { + if ( strpos($referer,$from) !== false ) + { + $referer = $to; + } + } + + $url = 'index.php?a=login¬ice=1&goto='.urlencode($referer); + header('Location: '.$url); + exit(); + } + else + { + hesk_session_regenerate_id(); + + // Need to update permissions? + if ( empty($_SESSION['isadmin']) ) + { + $res = hesk_dbQuery("SELECT `isadmin`, `categories`, `heskprivileges` FROM `".$hesk_settings['db_pfix']."users` WHERE `id` = '".intval($_SESSION['id'])."' LIMIT 1"); + if (hesk_dbNumRows($res) == 1) + { + $me = hesk_dbFetchAssoc($res); + foreach ($me as $k => $v) + { + $_SESSION[$k]=$v; + } + + // Get allowed categories + if (empty($_SESSION['isadmin']) ) + { + $_SESSION['categories']=explode(',',$_SESSION['categories']); + } + } + else + { + hesk_session_stop(); + $url = 'index.php?a=login¬ice=1&goto='.urlencode($referer); + header('Location: '.$url); + exit(); + } + } + + // Users online + if ($hesk_settings['online']) + { + require(HESK_PATH . 'inc/users_online.inc.php'); + hesk_initOnline($_SESSION['id']); + } + + return true; + } + +} // END hesk_isLoggedIn() + + +function hesk_Pass2Hash($plaintext) { + $majorsalt = ''; + $len = strlen($plaintext); + for ($i=0;$i<$len;$i++) + { + $majorsalt .= sha1(substr($plaintext,$i,1)); + } + $corehash = sha1($majorsalt); + return $corehash; +} // END hesk_Pass2Hash() + + +function hesk_formatDate($dt) +{ + $dt=hesk_date($dt); + $dt=str_replace(' ','
    ',$dt); + return $dt; +} // End hesk_formatDate() + + +function hesk_jsString($str) +{ + $str = str_replace( array('\'','
    ') , array('\\\'','') ,$str); + $from = array("/\r\n|\n|\r/", '/\([^\<]*)\<\/a\>/i', '/\([^\<]*)\<\/a\>/i'); + $to = array("\\r\\n' + \r\n'", "$1", "$1"); + return preg_replace($from,$to,$str); +} // END hesk_jsString() + + +function hesk_myCategories($what='category') +{ + if ( ! empty($_SESSION['isadmin']) ) + { + return '1'; + } + else + { + return " `".hesk_dbEscape($what)."` IN ('" . implode("','", array_map('intval', $_SESSION['categories']) ) . "')"; + } +} // END hesk_myCategories() + + +function hesk_okCategory($cat,$error=1,$user_isadmin=false,$user_cat=false) +{ + global $hesklang; + + /* Checking for current user or someone else? */ + if ($user_isadmin === false) + { + $user_isadmin = $_SESSION['isadmin']; + } + + if ($user_cat === false) + { + $user_cat = $_SESSION['categories']; + } + + /* Is admin? */ + if ($user_isadmin) + { + return true; + } + /* Staff with access? */ + elseif (in_array($cat,$user_cat)) + { + return true; + } + /* No access */ + else + { + if ($error) + { + hesk_error($hesklang['not_authorized_tickets']); + } + else + { + return false; + } + } + +} // END hesk_okCategory() + + +function hesk_checkPermission($feature,$showerror=1) { + global $hesklang; + + + /* Check if this is for managing settings */ + if ($feature == 'can_manage_settings') + { + if ($_SESSION['can_manage_settings']) { + return true; + } else { + if ($showerror) { + hesk_error($hesklang['no_permission'].'

     

    '.$hesklang['click_login'].''); + } else { + return false; + } + } + } + + /* Admins have full access to all features, besides possibly settings */ + if ($_SESSION['isadmin']) + { + return true; + } + + /* Check other staff for permissions */ + if (strpos($_SESSION['heskprivileges'], $feature) === false) + { + if ($showerror) + { + hesk_error($hesklang['no_permission'].'

     

    '.$hesklang['click_login'].''); + } + else + { + return false; + } + } + else + { + return true; + } + +} // END hesk_checkPermission() diff --git a/inc/email_functions.inc.php b/inc/email_functions.inc.php new file mode 100644 index 00000000..d8dc60ac --- /dev/null +++ b/inc/email_functions.inc.php @@ -0,0 +1,617 @@ + $myuser['email'], 'language' => $myuser['language']); + continue; + } + + /* Not admin, is he/she allowed this category? */ + $myuser['categories']=explode(',',$myuser['categories']); + if (in_array($ticket['category'],$myuser['categories'])) + { + $admins[] = array('email' => $myuser['email'], 'language' => $myuser['language']); + continue; + } + } + + if (count($admins) > 0) + { + /* Make sure each user gets email in his/her preferred language */ + $current_language = 'NONE'; + $recipients = array(); + + /* Loop through staff */ + foreach ($admins as $admin) + { + /* If admin language is NULL force default HESK language */ + if ( ! $admin['language'] || ! isset($hesk_settings['languages'][$admin['language']]) ) + { + $admin['language'] = HESK_DEFAULT_LANGUAGE; + } + + /* Generate message or add email to the list of recepients */ + if ($admin['language'] == $current_language) + { + /* We already have the message, just add email to the recipients list */ + $recipients[] = $admin['email']; + } + else + { + /* Send email messages in previous languages (if required) */ + if ($current_language != 'NONE') + { + /* Send e-mail to staff */ + hesk_mail(implode(',',$recipients), $subject, $message ); + + /* Reset list of email addresses */ + $recipients = array(); + } + + /* Set new language */ + hesk_setLanguage($admin['language']); + + /* Format staff email subject and message for this language */ + $subject = hesk_getEmailSubject($email_template,$ticket); + $message = hesk_getEmailMessage($email_template,$ticket,$is_ticket); + + /* Add email to the recipients list */ + $recipients[] = $admin['email']; + + /* Remember the last processed language */ + $current_language = $admin['language']; + } + } + + /* Send email messages to the remaining staff */ + hesk_mail(implode(',',$recipients), $subject, $message ); + + /* Reset language to original one */ + hesk_resetLanguage(); + } + + return true; + +} // END hesk_notifyStaff() + + +function hesk_validEmails() +{ + global $hesklang; + + return array( + + /*** Emails sent to CLIENT ***/ + + // --> Send reminder about existing tickets + 'forgot_ticket_id' => $hesklang['forgot_ticket_id'], + + // --> Staff replied to a ticket + 'new_reply_by_staff' => $hesklang['new_reply_by_staff'], + + // --> New ticket submitted + 'new_ticket' => $hesklang['ticket_received'], + + // --> Ticket closed + 'ticket_closed' => $hesklang['ticket_closed'], + + + /*** Emails sent to STAFF ***/ + + // --> Ticket moved to a new category + 'category_moved' => $hesklang['category_moved'], + + // --> Client replied to a ticket + 'new_reply_by_customer' => $hesklang['new_reply_by_customer'], + + // --> New ticket submitted + 'new_ticket_staff' => $hesklang['new_ticket_staff'], + + // --> New ticket assigned to staff + 'ticket_assigned_to_you'=> $hesklang['ticket_assigned_to_you'], + + // --> New private message + 'new_pm' => $hesklang['new_pm'], + + // --> New note by someone to a ticket assigned to you + 'new_note' => $hesklang['new_note'], + + ); +} // END hesk_validEmails() + + +function hesk_mail($to,$subject,$message) +{ + global $hesk_settings, $hesklang; + + // Demo mode + if ( defined('HESK_DEMO') ) + { + return true; + } + + // Encode subject to UTF-8 + $subject = "=?UTF-8?B?" . base64_encode( hesk_html_entity_decode($subject) ) . "?="; + + // Setup "name " for headers + if ($hesk_settings['noreply_name']) + { + $hesk_settings['from_header'] = "=?UTF-8?B?" . base64_encode( hesk_html_entity_decode($hesk_settings['noreply_name']) ) . "?= <" . $hesk_settings['noreply_mail'] . ">"; + } + else + { + $hesk_settings['from_header'] = $hesk_settings['noreply_mail']; + } + + // Uncomment for debugging + # echo "

    TO: $to
    SUBJECT: $subject
    MSG: $message

    "; + # return true; + + // Use PHP's mail function + if ( ! $hesk_settings['smtp']) + { + // Set additional headers + $headers = "From: $hesk_settings[from_header]\n"; + $headers.= "Reply-To: $hesk_settings[from_header]\n"; + $headers.= "Return-Path: $hesk_settings[webmaster_mail]\n"; + $headers.= "Date: " . date(DATE_RFC2822) . "\n"; + $headers.= "Content-Type: text/plain; charset=" . $hesklang['ENCODING']; + + // Send using PHP mail() function + ob_start(); + mail($to,$subject,$message,$headers); + $tmp = trim(ob_get_contents()); + ob_end_clean(); + + return (strlen($tmp)) ? $tmp : true; + } + + // Use a SMTP server directly instead + $smtp = new smtp_class; + $smtp->host_name = $hesk_settings['smtp_host_name']; + $smtp->host_port = $hesk_settings['smtp_host_port']; + $smtp->timeout = $hesk_settings['smtp_timeout']; + $smtp->ssl = $hesk_settings['smtp_ssl']; + $smtp->start_tls = $hesk_settings['smtp_tls']; + $smtp->user = $hesk_settings['smtp_user']; + $smtp->password = hesk_htmlspecialchars_decode($hesk_settings['smtp_password']); + $smtp->debug = 1; + + // Start output buffering so that any errors don't break headers + ob_start(); + + // Send the e-mail using SMTP + $to_arr = explode(',',$to); + if ( ! $smtp->SendMessage($hesk_settings['noreply_mail'], $to_arr, array( + "From: $hesk_settings[from_header]", + "To: $to", + "Reply-To: $hesk_settings[from_header]", + "Return-Path: $hesk_settings[webmaster_mail]", + "Subject: " . $subject, + "Date: " . date(DATE_RFC2822), + "Content-Type: text/plain; charset=" . $hesklang['ENCODING'] + ), $message)) + { + // Suppress errors unless we are in debug mode + if ($hesk_settings['debug_mode']) + { + $error = $hesklang['cnsm'] . ' ' . $to . '

    ' . + $hesklang['error'] . ': ' . htmlspecialchars($smtp->error). '

    ' . + ''; + ob_end_clean(); + hesk_error($error); + } + else + { + $_SESSION['HESK_2ND_NOTICE'] = true; + $_SESSION['HESK_2ND_MESSAGE'] = $hesklang['esf'] . ' ' . $hesklang['contact_webmsater'] . ' ' . $hesk_settings['webmaster_mail'] . ''; + } + } + + ob_end_clean(); + + return true; + +} // END hesk_mail() + + +function hesk_getEmailSubject($eml_file, $ticket='', $is_ticket=1, $strip=0) +{ + global $hesk_settings, $hesklang; + + // Demo mode + if ( defined('HESK_DEMO') ) + { + return ''; + } + + /* Get list of valid emails */ + $valid_emails = hesk_validEmails(); + + /* Verify this is a valid email include */ + if ( ! isset($valid_emails[$eml_file])) + { + hesk_error($hesklang['inve']); + } + else + { + $msg = $valid_emails[$eml_file]; + } + + /* If not a ticket-related email return subject as is */ + if ( ! $ticket ) + { + return $msg; + } + + /* Strip slashes from the subject only if it's a new ticket */ + if ($strip) + { + $ticket['subject'] = stripslashes($ticket['subject']); + } + + /* Not a ticket, but has some info in the $ticket array */ + if ( ! $is_ticket) + { + return str_replace('%%SUBJECT%%', $ticket['subject'], $msg); + } + + /* Set category title */ + $ticket['category'] = hesk_msgToPlain(hesk_getCategoryName($ticket['category']), 1); + + /* Get priority */ + switch ($ticket['priority']) + { + case 0: + $ticket['priority'] = $hesklang['critical']; + break; + case 1: + $ticket['priority'] = $hesklang['high']; + break; + case 2: + $ticket['priority'] = $hesklang['medium']; + break; + default: + $ticket['priority'] = $hesklang['low']; + } + + /* Set status */ + switch ($ticket['status']) + { + case 1: + $ticket['status'] = $hesklang['wait_reply']; + break; + case 2: + $ticket['status'] = $hesklang['replied']; + break; + case 3: + $ticket['status'] = $hesklang['closed']; + break; + case 4: + $ticket['status'] = $hesklang['in_progress']; + break; + case 5: + $ticket['status'] = $hesklang['on_hold']; + break; + default: + $ticket['status'] = $hesklang['open']; + } + + /* Replace all special tags */ + $msg = str_replace('%%SUBJECT%%', $ticket['subject'], $msg); + $msg = str_replace('%%TRACK_ID%%', $ticket['trackid'], $msg); + $msg = str_replace('%%CATEGORY%%', $ticket['category'], $msg); + $msg = str_replace('%%PRIORITY%%', $ticket['priority'], $msg); + $msg = str_replace('%%STATUS%%', $ticket['status'], $msg); + + return $msg; + +} // hesk_getEmailSubject() + + +function hesk_getEmailMessage($eml_file, $ticket, $is_admin=0, $is_ticket=1, $just_message=0) +{ + global $hesk_settings, $hesklang; + + // Demo mode + if ( defined('HESK_DEMO') ) + { + return ''; + } + + /* Get list of valid emails */ + $valid_emails = hesk_validEmails(); + + /* Verify this is a valid email include */ + if ( ! isset($valid_emails[$eml_file])) + { + hesk_error($hesklang['inve']); + } + + /* Get email template */ + $eml_file = 'language/' . $hesk_settings['languages'][$hesk_settings['language']]['folder'] . '/emails/' . $eml_file . '.txt'; + + if (file_exists(HESK_PATH . $eml_file)) + { + $msg = file_get_contents(HESK_PATH . $eml_file); + } + else + { + hesk_error($hesklang['emfm'].': '.$eml_file); + } + + /* Return just the message without any processing? */ + if ($just_message) + { + return $msg; + } + + // Convert any entities in site title to plain text + $hesk_settings['site_title'] = hesk_msgToPlain($hesk_settings['site_title'], 1); + + /* If it's not a ticket-related mail (like "a new PM") just process quickly */ + if ( ! $is_ticket) + { + $trackingURL = $hesk_settings['hesk_url'] . '/' . $hesk_settings['admin_dir'] . '/mail.php?a=read&id=' . intval($ticket['id']); + + $msg = str_replace('%%NAME%%', $ticket['name'] ,$msg); + $msg = str_replace('%%SUBJECT%%', $ticket['subject'] ,$msg); + $msg = str_replace('%%TRACK_URL%%', $trackingURL ,$msg); + $msg = str_replace('%%SITE_TITLE%%',$hesk_settings['site_title'] ,$msg); + $msg = str_replace('%%SITE_URL%%', $hesk_settings['site_url'] ,$msg); + + if ( isset($ticket['message']) ) + { + return str_replace('%%MESSAGE%%', $ticket['message'], $msg); + } + else + { + return $msg; + } + } + + // Is email required to view ticket (for customers only)? + $hesk_settings['e_param'] = $hesk_settings['email_view_ticket'] ? '&e=' . rawurlencode($ticket['email']) : ''; + + /* Generate the ticket URLs */ + $trackingURL = $hesk_settings['hesk_url']; + $trackingURL.= $is_admin ? '/' . $hesk_settings['admin_dir'] . '/admin_ticket.php' : '/ticket.php'; + $trackingURL.= '?track='.$ticket['trackid'].($is_admin ? '' : $hesk_settings['e_param']).'&Refresh='.rand(10000,99999); + + /* Set category title */ + $ticket['category'] = hesk_msgToPlain(hesk_getCategoryName($ticket['category']), 1); + + /* Set priority title */ + switch ($ticket['priority']) + { + case 0: + $ticket['priority'] = $hesklang['critical']; + break; + case 1: + $ticket['priority'] = $hesklang['high']; + break; + case 2: + $ticket['priority'] = $hesklang['medium']; + break; + default: + $ticket['priority'] = $hesklang['low']; + } + + /* Get owner name */ + $ticket['owner'] = hesk_msgToPlain( hesk_getOwnerName($ticket['owner']), 1); + + /* Set status */ + switch ($ticket['status']) + { + case 1: + $ticket['status'] = $hesklang['wait_reply']; + break; + case 2: + $ticket['status'] = $hesklang['replied']; + break; + case 3: + $ticket['status'] = $hesklang['closed']; + break; + case 4: + $ticket['status'] = $hesklang['in_progress']; + break; + case 5: + $ticket['status'] = $hesklang['on_hold']; + break; + default: + $ticket['status'] = $hesklang['open']; + } + + /* Replace all special tags */ + $msg = str_replace('%%NAME%%', $ticket['name'] ,$msg); + $msg = str_replace('%%SUBJECT%%', $ticket['subject'] ,$msg); + $msg = str_replace('%%TRACK_ID%%', $ticket['trackid'] ,$msg); + $msg = str_replace('%%TRACK_URL%%', $trackingURL ,$msg); + $msg = str_replace('%%SITE_TITLE%%',$hesk_settings['site_title'],$msg); + $msg = str_replace('%%SITE_URL%%', $hesk_settings['site_url'] ,$msg); + $msg = str_replace('%%CATEGORY%%', $ticket['category'] ,$msg); + $msg = str_replace('%%PRIORITY%%', $ticket['priority'] ,$msg); + $msg = str_replace('%%OWNER%%', $ticket['owner'] ,$msg); + $msg = str_replace('%%STATUS%%', $ticket['status'] ,$msg); + $msg = str_replace('%%EMAIL%%', $ticket['email'] ,$msg); + $msg = str_replace('%%CREATED%%', $ticket['dt'] ,$msg); + $msg = str_replace('%%UPDATED%%', $ticket['lastchange'] ,$msg); + + /* All custom fields */ + foreach ($hesk_settings['custom_fields'] as $k=>$v) + { + if ($v['use']) + { + if ($v['type'] == 'checkbox') + { + $ticket[$k] = str_replace("
    ","\n",$ticket[$k]); + } + + $msg = str_replace('%%'.strtoupper($k).'%%',stripslashes($ticket[$k]),$msg); + } + else + { + $msg = str_replace('%%'.strtoupper($k).'%%','',$msg); + } + } + + // Is message tag in email template? + if (strpos($msg, '%%MESSAGE%%') !== false) + { + // Replace message + $msg = str_replace('%%MESSAGE%%',$ticket['message'],$msg); + + // Add direct links to any attachments at the bottom of the email message + if ($hesk_settings['attachments']['use'] && isset($ticket['attachments']) && strlen($ticket['attachments']) ) + { + $msg .= "\n\n\n" . $hesklang['fatt']; + + $att = explode(',', substr($ticket['attachments'], 0, -1)); + foreach ($att as $myatt) + { + list($att_id, $att_name) = explode('#', $myatt); + $msg .= "\n\n" . $att_name . "\n" . $hesk_settings['hesk_url'] . '/download_attachment.php?att_id='.$att_id.'&track='.$ticket['trackid'].$hesk_settings['e_param']; + } + } + + // For customer notifications: if we allow email piping/pop 3 fetching and + // stripping quoted replies add an "reply above this line" tag + if ( ! $is_admin && ($hesk_settings['email_piping'] || $hesk_settings['pop3']) && $hesk_settings['strip_quoted']) + { + $msg = $hesklang['EMAIL_HR'] . "\n\n" . $msg; + } + } + + return $msg; + +} // END hesk_getEmailMessage diff --git a/language/en/emails/ticket_closed.txt b/language/en/emails/ticket_closed.txt new file mode 100644 index 00000000..51cfb97c --- /dev/null +++ b/language/en/emails/ticket_closed.txt @@ -0,0 +1,14 @@ +Dear %%NAME%%, + +Your support ticket "%%SUBJECT%%" has been updated to a closed/resolved status. + +Ticket tracking ID: %%TRACK_ID%% + +You can view the status of your ticket here: +%%TRACK_URL%% + + +Sincerely, + +%%SITE_TITLE%% +%%SITE_URL%% \ No newline at end of file diff --git a/language/en/text.php b/language/en/text.php index 23eb6d45..14e9c087 100644 --- a/language/en/text.php +++ b/language/en/text.php @@ -21,6 +21,11 @@ $hesklang['_COLLATE']='utf8_unicode_ci'; // This is the email break line that will be used in email piping $hesklang['EMAIL_HR']='------ Reply above this line ------'; +// ADDED OR MODIFIED IN Mods For Hesk 1.6.0 +$hesklang['ticket_closed'] = '[#%%TRACK_ID%%] Ticket closed/resolved'; +$hesklang['ticket_reopen'] = '[#%%TRACK_ID%%] Ticket reopened'; +$hesklang['ticket_reopen_assigned'] = '[#%%TRACK_ID%%] Assigned ticket reopened'; + // ADDED OR MODIFIED IN NuMods 1.5.0 $hesklang['ticket_auto_refresh'] = 'Ticket Table Auto-Refresh:'; $hesklang['display_rtl'] = 'Display site right-to-left'; From 8915114b429460123ca94d8166f07071f32f33e6 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 23 Nov 2014 15:31:38 -0500 Subject: [PATCH 126/208] Closes #63 open links in tickets in new tab / window Typically, users should be given the ability to open links in the same window. However, according to HTML5 specifications, the _blank target attribute is now permitted for specific use cases. Opening external links, in my opinion, is a valid use case. --- inc/common.inc.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inc/common.inc.php b/inc/common.inc.php index e971fab5..1ba32f78 100644 --- a/inc/common.inc.php +++ b/inc/common.inc.php @@ -1310,7 +1310,7 @@ function make_clickable_callback($type, $whitespace, $url, $relative_url, $class $text = htmlspecialchars($text); $append = htmlspecialchars($append); - $html = "$whitespace$text$append"; + $html = "$whitespace$text$append"; return $html; } // END make_clickable_callback() From 219b722917c07875f49b813e07500c1d6bef231a Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 23 Nov 2014 22:35:09 -0500 Subject: [PATCH 127/208] Closes #74: A new ticket can be modeled after an existing ticket A dropdown on creation was not feasible, but this works just as well and can be used outside of HESK --- admin/admin_ticket.php | 34 ++++++++++++++++++++++++++----- admin/new_ticket.php | 43 ++++++++++++++++++++++++++++++---------- css/hesk_newStyle.php | 1 + css/hesk_newStyleRTL.php | 1 + language/en/text.php | 1 + 5 files changed, 65 insertions(+), 15 deletions(-) diff --git a/admin/admin_ticket.php b/admin/admin_ticket.php index d0e2eb6e..c250032c 100644 --- a/admin/admin_ticket.php +++ b/admin/admin_ticket.php @@ -630,13 +630,13 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
    -
    +

    -
    +

    -
    +
    fetch_assoc(); $isTicketClosed = $isTicketClosedRow['IsClosed']; + echo '
    '; if ($isTicketClosed == 0) // Ticket is still open { echo ''.$hesklang['close_action'].''; + class="btn btn-default btn-sm" href="change_status.php?track='.$trackingID.'&s='.$staffClosedOptionStatus['ID'].'&Refresh='.$random.'&token='.hesk_token_echo(0).'"> + '.$hesklang['close_action'].''; } else { echo ''.$hesklang['open_action'].''; + class="btn btn-default btn-sm" href="change_status.php?track='.$trackingID.'&s='.$staffReopenedStatus['ID'].'&Refresh='.$random.'&token='.hesk_token_echo(0).'"> + '.$hesklang['open_action'].''; } + + $linkText = 'new_ticket.php?name='.$ticket['name'].'&email='.$ticket['email'].'&catid='.$category['id'].'&priority='.$ticket['priority']; + foreach ($hesk_settings['custom_fields'] as $k=>$v) + { + if ($v['use'] == 1) + { + + if ($v['type'] == 'checkbox') + { + $value = str_replace('
    ', '-CHECKBOX-', $ticket[$k]); + } else { + $value = $ticket[$k]; + } + $linkText .= '&c_'.$k.'='.$value; + } + } + + echo ' + '.$hesklang['create_based_on_contact'].' + '; + echo '
    '; ?>
    diff --git a/admin/new_ticket.php b/admin/new_ticket.php index e6ff91ae..84a0a323 100644 --- a/admin/new_ticket.php +++ b/admin/new_ticket.php @@ -116,13 +116,19 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php'); ';} else {echo '
    ';} ?>
    - +
    - placeholder=""/> + + placeholder="">
    @@ -154,10 +160,18 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
    @@ -174,7 +188,7 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php'); // Staff doesn't need to fill in required custom fields $v['req'] = ''; - if ($v['type'] == 'checkbox') + if ($v['type'] == 'checkbox' && !isset($_GET["c_$k"])) { $k_value = array(); if (isset($_SESSION["c_$k"]) && is_array($_SESSION["c_$k"])) @@ -189,6 +203,16 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php'); { $k_value = stripslashes(hesk_input($_SESSION["c_$k"])); } + elseif (isset($_GET["c_$k"])) + { + if ($v['type'] == 'checkbox') + { + $k_value = explode('-CHECKBOX-', $_GET["c_$k"]); + } else + { + $k_value = stripslashes(hesk_GET("c_$k")); + } + } else { $k_value = ''; @@ -254,8 +278,7 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php'); /* Checkbox */ case 'checkbox': echo '
    '; - - $options = explode('#HESK#',$v['value']); + $options = explode('#HESK#',$v['value']); $cls = in_array($k,$_SESSION['iserror']) ? ' class="isError" ' : ''; foreach ($options as $option) @@ -311,7 +334,7 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php'); ';} else {echo '
    ';} ?>
    - +
    ';} else {echo '
    ';} ?> diff --git a/css/hesk_newStyle.php b/css/hesk_newStyle.php index 32ef5dd1..6f357be1 100644 --- a/css/hesk_newStyle.php +++ b/css/hesk_newStyle.php @@ -39,6 +39,7 @@ @media (min-width:992px) { .close-ticket { text-align: right; + padding-bottom: 5px; } } diff --git a/css/hesk_newStyleRTL.php b/css/hesk_newStyleRTL.php index 0abbd51d..371395d7 100644 --- a/css/hesk_newStyleRTL.php +++ b/css/hesk_newStyleRTL.php @@ -39,6 +39,7 @@ @media (min-width:992px) { .close-ticket { text-align: left; + padding-bottom: 5px; } } diff --git a/language/en/text.php b/language/en/text.php index 14e9c087..2694b45c 100644 --- a/language/en/text.php +++ b/language/en/text.php @@ -25,6 +25,7 @@ $hesklang['EMAIL_HR']='------ Reply above this line ------'; $hesklang['ticket_closed'] = '[#%%TRACK_ID%%] Ticket closed/resolved'; $hesklang['ticket_reopen'] = '[#%%TRACK_ID%%] Ticket reopened'; $hesklang['ticket_reopen_assigned'] = '[#%%TRACK_ID%%] Assigned ticket reopened'; +$hesklang['create_based_on_contact'] = 'Create Ticket For Same Contact'; // ADDED OR MODIFIED IN NuMods 1.5.0 $hesklang['ticket_auto_refresh'] = 'Ticket Table Auto-Refresh:'; From 3d4c0a99b709e31efb52404725c8437f6f3fc03b Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Mon, 24 Nov 2014 21:46:08 -0500 Subject: [PATCH 128/208] #66 Business Logic portion of emails to admins are done. Still need to add the option to the edit user / profile page --- admin/admin_ticket.php | 74 ++++++++++++++++++++---------------------- 1 file changed, 35 insertions(+), 39 deletions(-) diff --git a/admin/admin_ticket.php b/admin/admin_ticket.php index c250032c..35b752ec 100644 --- a/admin/admin_ticket.php +++ b/admin/admin_ticket.php @@ -241,51 +241,47 @@ if (isset($_POST['notemsg']) && hesk_token_check('POST')) hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."notes` (`ticket`,`who`,`dt`,`message`) VALUES ('".intval($ticket['id'])."','".intval($_SESSION['id'])."',NOW(),'".hesk_dbEscape($msg)."')"); /* Notify assigned staff that a note has been added if needed */ - if ($ticket['owner'] && $ticket['owner'] != $_SESSION['id']) - { - $res = hesk_dbQuery("SELECT `email`, `notify_note` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."users` WHERE `id`='".intval($ticket['owner'])."' LIMIT 1"); + $users = hesk_dbQuery("SELECT `email`, `notify_note` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."users` WHERE (`id`='".intval($ticket['owner'])."' OR (`isadmin` = '1' AND `notify_note_unassigned` = '1')) AND `id` <> '".intval($_SESSION['id'])."'"); - if (hesk_dbNumRows($res) == 1) - { - $owner = hesk_dbFetchAssoc($res); - - // 1. Generate the array with ticket info that can be used in emails - $info = array( - 'email' => $ticket['email'], - 'category' => $ticket['category'], - 'priority' => $ticket['priority'], - 'owner' => $ticket['owner'], - 'trackid' => $ticket['trackid'], - 'status' => $ticket['status'], - 'name' => $_SESSION['name'], - 'lastreplier' => $ticket['lastreplier'], - 'subject' => $ticket['subject'], - 'message' => stripslashes($msg), - 'dt' => hesk_date($ticket['dt'], true), - 'lastchange' => hesk_date($ticket['lastchange'], true), - ); - - // 2. Add custom fields to the array - foreach ($hesk_settings['custom_fields'] as $k => $v) - { - $info[$k] = $v['use'] ? $ticket[$k] : ''; - } + if (hesk_dbNumRows($users) > 0) + { + // 1. Generate the array with ticket info that can be used in emails + $info = array( + 'email' => $ticket['email'], + 'category' => $ticket['category'], + 'priority' => $ticket['priority'], + 'owner' => $ticket['owner'], + 'trackid' => $ticket['trackid'], + 'status' => $ticket['status'], + 'name' => $_SESSION['name'], + 'lastreplier' => $ticket['lastreplier'], + 'subject' => $ticket['subject'], + 'message' => stripslashes($msg), + 'dt' => hesk_date($ticket['dt'], true), + 'lastchange' => hesk_date($ticket['lastchange'], true), + ); + + // 2. Add custom fields to the array + foreach ($hesk_settings['custom_fields'] as $k => $v) + { + $info[$k] = $v['use'] ? $ticket[$k] : ''; + } - // 3. Make sure all values are properly formatted for email - $ticket = hesk_ticketToPlain($info, 1, 0); + // 3. Make sure all values are properly formatted for email + $ticket = hesk_ticketToPlain($info, 1, 0); - /* Get email functions */ - require(HESK_PATH . 'inc/email_functions.inc.php'); + /* Get email functions */ + require(HESK_PATH . 'inc/email_functions.inc.php'); - /* Format email subject and message for staff */ - $subject = hesk_getEmailSubject('new_note',$ticket); - $message = hesk_getEmailMessage('new_note',$ticket,1); + /* Format email subject and message for staff */ + $subject = hesk_getEmailSubject('new_note',$ticket); + $message = hesk_getEmailMessage('new_note',$ticket,1); - /* Send email to staff */ - hesk_mail($owner['email'], $subject, $message); - } + /* Send email to staff */ + while ($user = hesk_dbFetchAssoc($users)) { + hesk_mail($user['email'], $subject, $message); + } } - } header('Location: admin_ticket.php?track='.$trackingID.'&Refresh='.mt_rand(10000,99999)); exit(); From 6caaead8906d012c0d893f506317ad0ef96438e5 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Mon, 24 Nov 2014 21:57:10 -0500 Subject: [PATCH 129/208] Closes #66 Update the UI to allow users to change note emails --- admin/profile.php | 9 +++++++-- language/en/text.php | 1 + 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/admin/profile.php b/admin/profile.php index 7fad65db..e4df8727 100644 --- a/admin/profile.php +++ b/admin/profile.php @@ -311,14 +311,17 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
    + +
    -
    +
    @@ -419,6 +422,7 @@ function update_profile() { $_SESSION['new']['notify_reply_my'] = empty($_POST['notify_reply_my']) ? 0 : 1; $_SESSION['new']['notify_assigned'] = empty($_POST['notify_assigned']) ? 0 : 1; $_SESSION['new']['notify_note'] = empty($_POST['notify_note']) ? 0 : 1; + $_SESSION['new']['notify_note_unassigned'] = empty($_POST['notify_note_unassigned']) ? 0 : 1; $_SESSION['new']['notify_pm'] = empty($_POST['notify_pm']) ? 0 : 1; $_SESSION['new']['default_notify_customer_email'] = empty($_POST['default_notify_customer_email']) ? 1 : 0; @@ -451,6 +455,7 @@ function update_profile() { `notify_assigned`='".intval($_SESSION['new']['notify_assigned'])."' , `notify_pm`='".intval($_SESSION['new']['notify_pm'])."', `notify_note`='".intval($_SESSION['new']['notify_note'])."', + `notify_note_unassigned`='".intval($_SESSION['new']['notify_note_unassigned'])."', `default_notify_customer_email`='".intval($_SESSION['new']['default_notify_customer_email'])."' WHERE `id`='".intval($_SESSION['id'])."' LIMIT 1" ); diff --git a/language/en/text.php b/language/en/text.php index 2694b45c..e5fe01a1 100644 --- a/language/en/text.php +++ b/language/en/text.php @@ -26,6 +26,7 @@ $hesklang['ticket_closed'] = '[#%%TRACK_ID%%] Ticket closed/resolved'; $hesklang['ticket_reopen'] = '[#%%TRACK_ID%%] Ticket reopened'; $hesklang['ticket_reopen_assigned'] = '[#%%TRACK_ID%%] Assigned ticket reopened'; $hesklang['create_based_on_contact'] = 'Create Ticket For Same Contact'; +$hesklang['notify_note_unassigned'] = 'Someone adds a note to a ticket not assigned to me'; // ADDED OR MODIFIED IN NuMods 1.5.0 $hesklang['ticket_auto_refresh'] = 'Ticket Table Auto-Refresh:'; From db34f581d05499f66edb074ce86a6146acc3bb7a Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Mon, 24 Nov 2014 21:58:39 -0500 Subject: [PATCH 130/208] Update README.md --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 31e75c16..013b73d1 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,4 @@ -[![Stories in Ready](https://badge.waffle.io/mkoch227/Mods-For-Hesk.png?label=ready&title=Ready)](https://waffle.io/mkoch227/Mods-For-Hesk) -[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/mkoch227/mods-for-hesk/trend.png)](https://bitdeli.com/free "Bitdeli Badge") +[![Stories in Ready](https://badge.waffle.io/mkoch227/Mods-For-Hesk.png?label=waffle:ready&title=Ready)](https://waffle.io/mkoch227/Mods-For-Hesk)

    NuMods v1.5.0

    This branch contains all files modified from the base version of HESK to become NuMods, a set of modifications for HESK v2.x From 855b66b1f392f6a44140fa89d09512fecb29488f Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Mon, 24 Nov 2014 23:07:56 -0500 Subject: [PATCH 131/208] Updated note email text --- .gitignore | 1 - language/en/emails/new_note.txt | 17 +++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 language/en/emails/new_note.txt diff --git a/.gitignore b/.gitignore index fd26d961..0787cb13 100644 --- a/.gitignore +++ b/.gitignore @@ -251,7 +251,6 @@ install/update.php language/en/emails/category_moved.txt language/en/emails/forgot_ticket_id.txt language/en/emails/index.htm -language/en/emails/new_note.txt language/en/emails/new_pm.txt language/en/emails/new_reply_by_customer.txt language/en/emails/new_reply_by_staff.txt diff --git a/language/en/emails/new_note.txt b/language/en/emails/new_note.txt new file mode 100644 index 00000000..edad8921 --- /dev/null +++ b/language/en/emails/new_note.txt @@ -0,0 +1,17 @@ +Hello, + +A new note has been added to ticket "%%SUBJECT%%". + +Note by %%NAME%%: + +%%MESSAGE%% + + +You can manage this ticket here: +%%TRACK_URL%% + + +Regards, + +%%SITE_TITLE%% +%%SITE_URL%% \ No newline at end of file From c295201f52902ddf8248ac2c00bbc9e0670d216b Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Mon, 24 Nov 2014 23:24:53 -0500 Subject: [PATCH 132/208] #80 Move pre-1.4.0 scripts to freshInstall file --- install/freshInstall.php | 44 +++++++++++++++++++++++++ install/updateNuMods.php | 69 +--------------------------------------- 2 files changed, 45 insertions(+), 68 deletions(-) create mode 100644 install/freshInstall.php diff --git a/install/freshInstall.php b/install/freshInstall.php new file mode 100644 index 00000000..d7d9fef1 --- /dev/null +++ b/install/freshInstall.php @@ -0,0 +1,44 @@ +num_rows == 0); - $showInstructions = 'none'; - $showFinished = 'block'; - - if ($shouldBuildTable) - { - $showInstructions = 'none'; - $showFinished = 'block'; - - //-- Need to do this since we are no longer restricted on IDs and we want an INT for proper INNER JOINs - hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` CHANGE COLUMN `status` `status` INT NOT NULL DEFAULT '0'"); - - hesk_dbQuery("CREATE TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."statuses` ( - `ID` INT NOT NULL, - `ShortNameContentKey` TEXT NOT NULL, - `TicketViewContentKey` TEXT NOT NULL, - `TextColor` TEXT NOT NULL, - `IsNewTicketStatus` BIT NOT NULL DEFAULT 0, - `IsClosed` BIT NOT NULL DEFAULT 0, - `IsClosedByClient` BIT NOT NULL DEFAULT 0, - `IsCustomerReplyStatus` BIT NOT NULL DEFAULT 0, - `IsStaffClosedOption` BIT NOT NULL DEFAULT 0, - `IsStaffReopenedStatus` BIT NOT NULL DEFAULT 0, - `IsDefaultStaffReplyStatus` BIT NOT NULL DEFAULT 0, - `LockedTicketStatus` BIT NOT NULL DEFAULT 0, - PRIMARY KEY (`ID`))"); - hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."statuses` (ID, ShortNameContentKey, TicketViewContentKey, TextColor, IsNewTicketStatus, IsClosed, IsClosedByClient, IsCustomerReplyStatus, - IsStaffClosedOption, IsStaffReopenedStatus, IsDefaultStaffReplyStatus, LockedTicketStatus) - VALUES (0, 'open', 'open', '#FF0000', 1, 0, 0, 0, 0, 0, 0, 0);"); - - hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."statuses` (ID, ShortNameContentKey, TicketViewContentKey, TextColor, IsNewTicketStatus, IsClosed, IsClosedByClient, IsCustomerReplyStatus, - IsStaffClosedOption, IsStaffReopenedStatus, IsDefaultStaffReplyStatus, LockedTicketStatus) - VALUES (1, 'wait_reply', 'wait_staff_reply', '#FF9933', 0, 0, 0, 1, 0, 1, 0, 0);"); - hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."statuses` (ID, ShortNameContentKey, TicketViewContentKey, TextColor, IsNewTicketStatus, IsClosed, IsClosedByClient, IsCustomerReplyStatus, - IsStaffClosedOption, IsStaffReopenedStatus, IsDefaultStaffReplyStatus, LockedTicketStatus) - VALUES (2, 'replied', 'wait_cust_reply', '#0000FF', 0, 0, 0, 0, 0, 0, 1, 0);"); - hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."statuses` (ID, ShortNameContentKey, TicketViewContentKey, TextColor, IsNewTicketStatus, IsClosed, IsClosedByClient, IsCustomerReplyStatus, - IsStaffClosedOption, IsStaffReopenedStatus, IsDefaultStaffReplyStatus, LockedTicketStatus) - VALUES (3, 'resolved', 'resolved', '#008000', 0, 1, 1, 0, 1, 0, 0, 1);"); - hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."statuses` (ID, ShortNameContentKey, TicketViewContentKey, TextColor, IsNewTicketStatus, IsClosed, IsClosedByClient, IsCustomerReplyStatus, - IsStaffClosedOption, IsStaffReopenedStatus, IsDefaultStaffReplyStatus, LockedTicketStatus) - VALUES (4, 'in_progress', 'in_progress', '#000000', 0, 0, 0, 0, 0, 0, 0, 0);"); - hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."statuses` (ID, ShortNameContentKey, TicketViewContentKey, TextColor, IsNewTicketStatus, IsClosed, IsClosedByClient, IsCustomerReplyStatus, - IsStaffClosedOption, IsStaffReopenedStatus, IsDefaultStaffReplyStatus, LockedTicketStatus) - VALUES (5, 'on_hold', 'on_hold', '#000000', 0, 0, 0, 0, 0, 0, 0, 0);"); - hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."users` ADD COLUMN `autorefresh` BIGINT NOT NULL DEFAULT 0 AFTER `replies`;"); - hesk_dbQuery("CREATE TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."denied_ips` ( - `ID` INT NOT NULL PRIMARY KEY AUTO_INCREMENT, - `RangeStart` VARCHAR(100) NOT NULL, - `RangeEnd` VARCHAR(100) NOT NULL)"); - hesk_dbQuery("CREATE TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."denied_emails` (ID INT NOT NULL PRIMARY KEY AUTO_INCREMENT, Email VARCHAR(100) NOT NULL);"); - hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` ADD COLUMN `parent` MEDIUMINT(8) NULL AFTER `custom20`;"); - hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."users` ADD COLUMN `active` BIT NOT NULL DEFAULT 1 AFTER `autorefresh`"); - hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."users` ADD COLUMN `can_manage_settings` INT NOT NULL DEFAULT 1"); - hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."users` ADD COLUMN `default_notify_customer_email` ENUM ('0', '1') NOT NULL DEFAULT '1'"); - } -} - ?> @@ -88,12 +25,8 @@ if ($_GET['update'] == 1)

    Database User:

    Database Password:

    Database Prefix:

    - Proceed with installation + Proceed with installation

    By proceeding, you agree to the terms of the Creative Commons Attribution-ShareAlike 4.0 International License.

    -
    -

    Installation Finished

    -

    The installation of NuMods has finished. You can now delete the install directory and access the admin area

    -
    From e6ff3d2514d68b142aeda6e271f8edfd9cf4675d Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Mon, 24 Nov 2014 23:25:06 -0500 Subject: [PATCH 133/208] #80 Added migration script for current 1.6.0 changes --- install/updateTo1-5-0.php | 5 ++--- install/updateTo1-6-0.php | 11 +++++++++++ 2 files changed, 13 insertions(+), 3 deletions(-) create mode 100644 install/updateTo1-6-0.php diff --git a/install/updateTo1-5-0.php b/install/updateTo1-5-0.php index b283807a..78bce33d 100644 --- a/install/updateTo1-5-0.php +++ b/install/updateTo1-5-0.php @@ -7,7 +7,6 @@ hesk_dbConnect(); hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."users` ADD COLUMN `active` ENUM('0', '1') NOT NULL DEFAULT '1'"); hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."users` ADD COLUMN `can_manage_settings` ENUM('0', '1') NOT NULL DEFAULT '1'"); hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."users` ADD COLUMN `default_notify_customer_email` ENUM ('0', '1') NOT NULL DEFAULT '1'"); -?> -

    Update complete!

    -

    Please delete the install folder for security reasons, and then proceed back to the Help Desk

    \ No newline at end of file +header('Location: updateTo1-6-0.php'); +?> \ No newline at end of file diff --git a/install/updateTo1-6-0.php b/install/updateTo1-6-0.php new file mode 100644 index 00000000..5dbf0543 --- /dev/null +++ b/install/updateTo1-6-0.php @@ -0,0 +1,11 @@ + + +

    Installation / Update complete!

    +

    Please delete the install folder for security reasons, and then proceed back to the Help Desk

    \ No newline at end of file From ad4fee1eb3e4682fe51335174435b4fe5a6885c3 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Mon, 24 Nov 2014 23:54:57 -0500 Subject: [PATCH 134/208] #84 Wired up the UI for changing notification setting permissions Only non-admins can be restricted from changing notifications. Admins still can change freely --- admin/manage_users.php | 38 ++++++++++++++++++++++++++++++++------ install/updateTo1-6-0.php | 1 + language/en/text.php | 1 + 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/admin/manage_users.php b/admin/manage_users.php index cdce6e1d..f7cbea07 100644 --- a/admin/manage_users.php +++ b/admin/manage_users.php @@ -263,7 +263,10 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php'); } echo ' />' . $hesklang[$k] . '
    '; } - ?> + ?> +
    + +
    @@ -551,7 +554,8 @@ function edit_user() if ( ! isset($_SESSION['save_userdata'])) { - $res = hesk_dbQuery("SELECT `user`,`pass`,`isadmin`,`name`,`email`,`signature`,`categories`,`autoassign`,`heskprivileges` AS `features`, `can_manage_settings`, `active` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."users` WHERE `id`='".intval($id)."' LIMIT 1"); + $res = hesk_dbQuery("SELECT `user`,`pass`,`isadmin`,`name`,`email`,`signature`,`categories`,`autoassign`,`heskprivileges` AS `features`, `can_manage_settings`, `active`, `can_change_notification_settings` + FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."users` WHERE `id`='".intval($id)."' LIMIT 1"); $_SESSION['userdata'] = hesk_dbFetchAssoc($res); /* Store original username for display until changes are saved successfully */ @@ -691,7 +695,21 @@ function edit_user() } echo ' />' . $hesklang[$k] . ' '; } - ?> + + $manageNotificationCheckboxState = ''; + if ( + isset($_SESSION['userdata']['can_change_notification_settings']) + && $_SESSION['userdata']['can_change_notification_settings'] == 1) + { + $manageNotificationCheckboxState = 'checked'; + } + + ?> +
    + +
    @@ -791,7 +809,8 @@ function new_user() $myuser['features'] = ''; } - hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."users` (`user`,`pass`,`isadmin`,`name`,`email`,`signature`,`categories`,`autoassign`,`heskprivileges`, `can_manage_settings` $sql_where) VALUES ( + hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."users` ( + `user`,`pass`,`isadmin`,`name`,`email`,`signature`,`categories`,`autoassign`,`heskprivileges`, `can_manage_settings`, `can_change_notification_settings` $sql_where) VALUES ( '".hesk_dbEscape($myuser['user'])."', '".hesk_dbEscape($myuser['pass'])."', '".intval($myuser['isadmin'])."', @@ -801,7 +820,8 @@ function new_user() '".hesk_dbEscape($myuser['categories'])."', '".intval($myuser['autoassign'])."', '".hesk_dbEscape($myuser['features'])."', - '".hesk_dbEscape($myuser['can_manage_settings'])."' + '".hesk_dbEscape($myuser['can_manage_settings'])."', + '".hesk_dbEscape($myuser['can_change_notification_settings'])."' $sql_what )" ); $_SESSION['seluser'] = hesk_dbInsertID(); @@ -893,7 +913,8 @@ function update_user() `active`='".intval($myuser['active'])."', `autoassign`='".intval($myuser['autoassign'])."', `heskprivileges`='".hesk_dbEscape($myuser['features'])."', - `can_manage_settings`='".hesk_dbEscape($myuser['can_manage_settings'])."' + `can_manage_settings`='".hesk_dbEscape($myuser['can_manage_settings'])."', + `can_change_notification_settings`='".hesk_dbEscape($myuser['can_change_notification_settings'])."' $sql_where WHERE `id`='".intval($myuser['id'])."' LIMIT 1"); @@ -918,6 +939,11 @@ function hesk_validateUserInfo($pass_required = 1, $redirect_to = './manage_user $myuser['signature'] = hesk_input( hesk_POST('signature') ); $myuser['autoassign'] = hesk_POST('autoassign') == 'Y' ? 1 : 0; $myuser['active'] = empty($_POST['active']) ? 0 : 1; + $myuser['can_change_notification_settings'] = empty($_POST['can_change_notification_settings']) ? 0 : 1; + if ($myuser['isadmin']) + { + $myuser['can_change_notification_settings'] = 1; + } /* If it's not admin at least one category and fature is required */ $myuser['categories'] = array(); diff --git a/install/updateTo1-6-0.php b/install/updateTo1-6-0.php index 5dbf0543..3e179003 100644 --- a/install/updateTo1-6-0.php +++ b/install/updateTo1-6-0.php @@ -5,6 +5,7 @@ require(HESK_PATH . 'install/install_functions.inc.php'); require(HESK_PATH . 'hesk_settings.inc.php'); hesk_dbConnect(); hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."users` ADD COLUMN `notify_note_unassigned` ENUM('0', '1') NOT NULL DEFAULT '0'"); +hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."users` ADD COLUMN `can_change_notification_settings` ENUM('0', '1') NOT NULL DEFAULT '1'"); ?>

    Installation / Update complete!

    diff --git a/language/en/text.php b/language/en/text.php index e5fe01a1..1130610e 100644 --- a/language/en/text.php +++ b/language/en/text.php @@ -27,6 +27,7 @@ $hesklang['ticket_reopen'] = '[#%%TRACK_ID%%] Ticket reopened'; $hesklang['ticket_reopen_assigned'] = '[#%%TRACK_ID%%] Assigned ticket reopened'; $hesklang['create_based_on_contact'] = 'Create Ticket For Same Contact'; $hesklang['notify_note_unassigned'] = 'Someone adds a note to a ticket not assigned to me'; +$hesklang['can_change_notification_settings'] = 'Can change notification settings'; // ADDED OR MODIFIED IN NuMods 1.5.0 $hesklang['ticket_auto_refresh'] = 'Ticket Table Auto-Refresh:'; From 26cfe83953081fbd6a080767a825c5bb1b53d2cf Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Tue, 25 Nov 2014 00:13:22 -0500 Subject: [PATCH 135/208] Closes #84: 'can_change_notification_settings' now respected by profile page --- admin/profile.php | 95 ++++++++++++++++++++++++++++---------------- language/en/text.php | 1 + 2 files changed, 61 insertions(+), 35 deletions(-) diff --git a/admin/profile.php b/admin/profile.php index e4df8727..fcb8c1d4 100644 --- a/admin/profile.php +++ b/admin/profile.php @@ -275,49 +275,74 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');

    + +
    +
    -
    - - - - -
    - - -
    - - - -
    -
    -
    - -
    - +
    + + + + + +
    + + + +
    + + + + + +
    +
    +
    + + + + + +
    + -
    diff --git a/language/en/text.php b/language/en/text.php index 1130610e..a2f57699 100644 --- a/language/en/text.php +++ b/language/en/text.php @@ -45,6 +45,7 @@ $hesklang['inactive_user'] = 'Your account is currently inactive. Contact an adm $hesklang['notify_customer_email'] = 'Emails to customer on reply'; $hesklang['notify_customer_email_text'] = 'Don\'t send email notifications of replies to the customer by default'; $hesklang['cant_edit_admin'] = 'You cannot edit the God Admin (User ID = 1)'; +$hesklang['notifications_disabled_info'] = 'Changing notifications settings has been disabled by your administrator.'; // ADDED OR MODIFIED IN NuMods 1.4.0 $hesklang['numods'] = 'NuMods'; From e84d9f32298d9e43fa437ffbba48ff7d7d9c359c Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Thu, 27 Nov 2014 01:19:30 -0500 Subject: [PATCH 136/208] Closes #68: Notes can be edited --- admin/admin_ticket.php | 47 ++++++++++++++++++++++++++++++++++++--- css/hesk_newStyle.php | 6 +++++ css/hesk_newStyleRTL.php | 6 +++++ install/updateTo1-6-0.php | 2 ++ js/nuMods-javascript.js | 11 +++++++++ language/en/text.php | 3 +++ 6 files changed, 72 insertions(+), 3 deletions(-) diff --git a/admin/admin_ticket.php b/admin/admin_ticket.php index 35b752ec..381bb0d1 100644 --- a/admin/admin_ticket.php +++ b/admin/admin_ticket.php @@ -401,6 +401,24 @@ if (isset($_GET['delatt']) && hesk_token_check()) hesk_process_messages($hesklang['kb_att_rem'],'admin_ticket.php?track='.$trackingID.'&Refresh='.mt_rand(10000,99999),'SUCCESS'); } +if (isset($_POST['note_message'])) { + $n = $_POST['note_id']; + if ($can_del_notes) + { + hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."notes` + SET `edit_date` = NOW(), `message` = '".hesk_dbEscape($_POST['note_message'])."', `number_of_edits` = `number_of_edits` + 1 + WHERE `id`='".intval($n)."' LIMIT 1"); + } + else + { + hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."notes` + SET `edit_date` = NOW(), `message` = '".hesk_dbEscape($_POST['note_message'])."', `number_of_edits` = `number_of_edits` + 1 + WHERE `id`='".intval($n)."' AND `who`='".intval($_SESSION['id'])."' LIMIT 1"); + } + hesk_process_messages($hesklang['note_edit_successful'],'admin_ticket.php?track='.$trackingID.'&Refresh='.mt_rand(10000,99999),'SUCCESS'); +} + + /* Print header */ require_once(HESK_PATH . 'inc/headerAdmin.inc.php'); @@ -814,10 +832,33 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php'); { ?>
    -
    -

    Delete Note

    +
    + +
    + + +   + + + +
    +

    -

    -

    +

    + + + + + + + + + 0) { ?> +

    +

    Installation / Update complete!

    diff --git a/js/nuMods-javascript.js b/js/nuMods-javascript.js index 2ac14462..f8100465 100644 --- a/js/nuMods-javascript.js +++ b/js/nuMods-javascript.js @@ -50,4 +50,15 @@ function toggleChildrenForm(show) { } } +function toggleNote(noteId, showForm) { + if (showForm) { + $('#note-' + noteId + '-p').hide(); + $('#note-' + noteId + '-form').show(); + } else { + $('#note-' + noteId + '-p').show(); + $('#note-' + noteId + '-form').hide(); + $('#note-' + noteId + '-textarea').val($('#note-' + noteId + '-p').text()) + } +} + jQuery(document).ready(loadJquery); diff --git a/language/en/text.php b/language/en/text.php index a2f57699..cf3b6aca 100644 --- a/language/en/text.php +++ b/language/en/text.php @@ -28,6 +28,9 @@ $hesklang['ticket_reopen_assigned'] = '[#%%TRACK_ID%%] Assigned ticket reopened' $hesklang['create_based_on_contact'] = 'Create Ticket For Same Contact'; $hesklang['notify_note_unassigned'] = 'Someone adds a note to a ticket not assigned to me'; $hesklang['can_change_notification_settings'] = 'Can change notification settings'; +$hesklang['note_edit_successful'] = 'Note edited'; +$hesklang['note_last_edit'] = 'Note last edited on: %s'; // %s: timestamp of last edit +$hesklang['total_number_of_edits'] = 'Total number of edits: %s'; // %s: total number of edits // ADDED OR MODIFIED IN NuMods 1.5.0 $hesklang['ticket_auto_refresh'] = 'Ticket Table Auto-Refresh:'; From f904afe21fd916de9df691b6a8b637331c43bd76 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Thu, 27 Nov 2014 10:48:26 -0500 Subject: [PATCH 137/208] #67 Write migration scripts for attachments for notes --- install/updateTo1-6-0.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/install/updateTo1-6-0.php b/install/updateTo1-6-0.php index 95b6ad32..50dfbdea 100644 --- a/install/updateTo1-6-0.php +++ b/install/updateTo1-6-0.php @@ -8,6 +8,8 @@ hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."users` AD hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."users` ADD COLUMN `can_change_notification_settings` ENUM('0', '1') NOT NULL DEFAULT '1'"); hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."notes` ADD COLUMN `edit_date` DATETIME NULL"); hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."notes` ADD COLUMN `number_of_edits` INT NOT NULL DEFAULT 0"); +hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."attachments` ADD COLUMN `note_id` INT NULL AFTER `ticket_id`"); +hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."attachments` MODIFY COLUMN `ticket_id` VARCHAR(13) NULL"); ?>

    Installation / Update complete!

    From 65a80089c0d3a0048e627dc8ff9d80b2287d56ab Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Thu, 27 Nov 2014 11:14:59 -0500 Subject: [PATCH 138/208] #67 Wired up part of the UI. Still need to add section to view attachments --- admin/admin_ticket.php | 33 +++++++++++++++++++++++++++------ js/nuMods-javascript.js | 8 ++++++++ language/en/text.php | 1 + 3 files changed, 36 insertions(+), 6 deletions(-) diff --git a/admin/admin_ticket.php b/admin/admin_ticket.php index 381bb0d1..cceb1a76 100644 --- a/admin/admin_ticket.php +++ b/admin/admin_ticket.php @@ -866,7 +866,6 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php'); ?>
    - :
    diff --git a/js/nuMods-javascript.js b/js/nuMods-javascript.js index f8100465..b3dc615c 100644 --- a/js/nuMods-javascript.js +++ b/js/nuMods-javascript.js @@ -61,4 +61,12 @@ function toggleNote(noteId, showForm) { } } +function addFileDialog(id, divId) { + + var nextId = +($('#'+id).text()); + $('#'+divId).append(''); + $('#'+id).text(nextId+1); + +} + jQuery(document).ready(loadJquery); diff --git a/language/en/text.php b/language/en/text.php index cf3b6aca..6878f536 100644 --- a/language/en/text.php +++ b/language/en/text.php @@ -31,6 +31,7 @@ $hesklang['can_change_notification_settings'] = 'Can change notification setting $hesklang['note_edit_successful'] = 'Note edited'; $hesklang['note_last_edit'] = 'Note last edited on: %s'; // %s: timestamp of last edit $hesklang['total_number_of_edits'] = 'Total number of edits: %s'; // %s: total number of edits +$hesklang['add_row'] = 'Add row'; // ADDED OR MODIFIED IN NuMods 1.5.0 $hesklang['ticket_auto_refresh'] = 'Ticket Table Auto-Refresh:'; From 2a9219cf2597ffffcf422b514a9f29795fcb48c1 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Fri, 28 Nov 2014 22:17:47 -0500 Subject: [PATCH 139/208] #67 Partial implementation of adding attachments to the notes view Still has things to fix and need to add deleting attachments --- admin/admin_ticket.php | 76 ++++++++++++++++++++++++++++++++--------- js/nuMods-javascript.js | 8 ----- language/en/text.php | 2 +- 3 files changed, 60 insertions(+), 26 deletions(-) diff --git a/admin/admin_ticket.php b/admin/admin_ticket.php index cceb1a76..a67594fc 100644 --- a/admin/admin_ticket.php +++ b/admin/admin_ticket.php @@ -39,6 +39,7 @@ define('HESK_PATH','../'); require(HESK_PATH . 'hesk_settings.inc.php'); require(HESK_PATH . 'inc/common.inc.php'); require(HESK_PATH . 'inc/admin_functions.inc.php'); +require(HESK_PATH . 'inc/posting_functions.inc.php'); hesk_load_database_functions(); hesk_session_start(); @@ -238,7 +239,32 @@ if (isset($_POST['notemsg']) && hesk_token_check('POST')) { /* Add note to database */ $msg = nl2br(hesk_makeURL($msg)); + hesk_dbInsertID(); hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."notes` (`ticket`,`who`,`dt`,`message`) VALUES ('".intval($ticket['id'])."','".intval($_SESSION['id'])."',NOW(),'".hesk_dbEscape($msg)."')"); + $noteId = hesk_dbInsertID(); + + /* Upload attachments to database */ + if ($hesk_settings['attachments']['use']) + { + require(HESK_PATH . 'inc/attachments.inc.php'); + $attachments = array(); + for ($i=1;$i<=$hesk_settings['attachments']['max_number'];$i++) + { + $att = hesk_uploadFile($i); + if ($att !== false && !empty($att)) + { + $attachments[$i] = $att; + } + } + } + if ($hesk_settings['attachments']['use'] && !empty($attachments)) + { + foreach ($attachments as $myatt) + { + hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."attachments` (`note_id`,`saved_name`,`real_name`,`size`) VALUES ('".hesk_dbEscape($noteId)."','".hesk_dbEscape($myatt['saved_name'])."','".hesk_dbEscape($myatt['real_name'])."','".intval($myatt['size'])."')"); + } + } + /* Notify assigned staff that a note has been added if needed */ $users = hesk_dbQuery("SELECT `email`, `notify_note` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."users` WHERE (`id`='".intval($ticket['owner'])."' OR (`isadmin` = '1' AND `notify_note_unassigned` = '1')) AND `id` <> '".intval($_SESSION['id'])."'"); @@ -625,7 +651,7 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php'); echo hesk_getAdminButtons(); ?>
    - +
    @@ -846,16 +872,30 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');

    -

    -

    - - - - - - - - +
    +
    +

    + + + + + + + + + +
    +
    + + '.$att_name.'
    '; + } ?> +
    +
    0) { ?>

    @@ -870,7 +910,7 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php'); if ($can_reply) { ?> -   +   @@ -888,12 +928,14 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
    - - +
    '; + } + + echo '' . $hesklang['ful'] . ''; + ?>
    - - -
    diff --git a/js/nuMods-javascript.js b/js/nuMods-javascript.js index b3dc615c..f8100465 100644 --- a/js/nuMods-javascript.js +++ b/js/nuMods-javascript.js @@ -61,12 +61,4 @@ function toggleNote(noteId, showForm) { } } -function addFileDialog(id, divId) { - - var nextId = +($('#'+id).text()); - $('#'+divId).append(''); - $('#'+id).text(nextId+1); - -} - jQuery(document).ready(loadJquery); diff --git a/language/en/text.php b/language/en/text.php index 6878f536..bdd1f2c8 100644 --- a/language/en/text.php +++ b/language/en/text.php @@ -32,6 +32,7 @@ $hesklang['note_edit_successful'] = 'Note edited'; $hesklang['note_last_edit'] = 'Note last edited on: %s'; // %s: timestamp of last edit $hesklang['total_number_of_edits'] = 'Total number of edits: %s'; // %s: total number of edits $hesklang['add_row'] = 'Add row'; +$hesklang['addnote']='Add note'; // ADDED OR MODIFIED IN NuMods 1.5.0 $hesklang['ticket_auto_refresh'] = 'Ticket Table Auto-Refresh:'; @@ -679,7 +680,6 @@ $hesklang['opt2']='Options for this radio button, enter one option per line (eac $hesklang['opt3']='Options for this select box, enter one option per line (each line will be a choice your customers can choose from). You need to enter at least two options!'; $hesklang['atl2']='Enter at least two options (one per line)!'; $hesklang['notes']='Notes'; -$hesklang['addnote']='+ Add note'; $hesklang['noteby']='Note by'; $hesklang['delnote']='Delete note'; $hesklang['noteerr']='Note already deleted or wrong parameters'; From e293aa2e17fb3329a94c13701441d6fda2599f9c Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Fri, 28 Nov 2014 22:21:20 -0500 Subject: [PATCH 140/208] Ignore the attachments directory --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 0787cb13..cb0c963a 100644 --- a/.gitignore +++ b/.gitignore @@ -265,3 +265,4 @@ readme.html robots.txt .idea/ attachments/__latest.txt +attachments From a1f7af11fc926600a195d79799041fc20dcdd363 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Fri, 28 Nov 2014 23:58:07 -0500 Subject: [PATCH 141/208] #67 Note attachments can now be downloaded --- .gitignore | 1 - admin/admin_ticket.php | 6 +- download_attachment.php | 174 ++++++++++++++++++++++++++++++++++++++++ language/en/text.php | 4 +- 4 files changed, 180 insertions(+), 5 deletions(-) create mode 100644 download_attachment.php diff --git a/.gitignore b/.gitignore index cb0c963a..32828f4a 100644 --- a/.gitignore +++ b/.gitignore @@ -12,7 +12,6 @@ docs/docs_style.css docs/index.html docs/quick-guide.html docs/step-by-step-guide.html -download_attachment.php file_limits.php footer.txt header.txt diff --git a/admin/admin_ticket.php b/admin/admin_ticket.php index a67594fc..aa656abf 100644 --- a/admin/admin_ticket.php +++ b/admin/admin_ticket.php @@ -888,11 +888,11 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
    diff --git a/download_attachment.php b/download_attachment.php new file mode 100644 index 00000000..a7b713b1 --- /dev/null +++ b/download_attachment.php @@ -0,0 +1,174 @@ + $chunksize) +{ + $handle = fopen($realpath, 'rb'); + $buffer = ''; + while ( ! feof($handle)) + { + set_time_limit(300); + $buffer = fread($handle, $chunksize); + echo $buffer; + flush(); + } + fclose($handle); +} +else +{ + readfile($realpath); +} + +exit(); +?> diff --git a/language/en/text.php b/language/en/text.php index bdd1f2c8..1b05a690 100644 --- a/language/en/text.php +++ b/language/en/text.php @@ -32,7 +32,9 @@ $hesklang['note_edit_successful'] = 'Note edited'; $hesklang['note_last_edit'] = 'Note last edited on: %s'; // %s: timestamp of last edit $hesklang['total_number_of_edits'] = 'Total number of edits: %s'; // %s: total number of edits $hesklang['add_row'] = 'Add row'; -$hesklang['addnote']='Add note'; +$hesklang['addnote'] = 'Add note'; +$hesklang['no_noteID'] = 'No Note ID'; +$hesklang['note_id_not_found'] = 'Note ID not found'; // ADDED OR MODIFIED IN NuMods 1.5.0 $hesklang['ticket_auto_refresh'] = 'Ticket Table Auto-Refresh:'; From bdd5402a2e8a02e36bb1413ba9067b514cb67ce7 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sat, 29 Nov 2014 00:07:20 -0500 Subject: [PATCH 142/208] Closes #67 Finished deleting attachments for notes --- admin/admin_ticket.php | 44 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/admin/admin_ticket.php b/admin/admin_ticket.php index aa656abf..64b9bef9 100644 --- a/admin/admin_ticket.php +++ b/admin/admin_ticket.php @@ -427,6 +427,45 @@ if (isset($_GET['delatt']) && hesk_token_check()) hesk_process_messages($hesklang['kb_att_rem'],'admin_ticket.php?track='.$trackingID.'&Refresh='.mt_rand(10000,99999),'SUCCESS'); } +/* Delete note attachment option */ +if (isset($_GET['delete-note-att']) && hesk_token_check()) { + if ( ! $can_delete || ! $can_edit) + { + hesk_process_messages($hesklang['no_permission'],'admin_ticket.php?track='.$trackingID.'&Refresh='.mt_rand(10000,99999)); + } + + $att_id = intval( hesk_GET('delete-note-att') ) or hesk_error($hesklang['inv_att_id']); + + $reply = intval( hesk_GET('reply', 0) ); + if ($reply < 1) + { + $reply = 0; + } + + /* Get attachment info */ + $res = hesk_dbQuery("SELECT * FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."attachments` WHERE `att_id`='".intval($att_id)."' LIMIT 1"); + if (hesk_dbNumRows($res) != 1) + { + hesk_process_messages($hesklang['id_not_valid'].' (att_id)','admin_ticket.php?track='.$trackingID.'&Refresh='.mt_rand(10000,99999)); + } + $att = hesk_dbFetchAssoc($res); + + /* Is note ID valid for this attachment? */ + if (!isset($_GET['note_id']) || $att['note_id'] != $_GET['note_id']) + { + hesk_process_messages($hesklang['trackID_not_found'],'admin_ticket.php?track='.$trackingID.'&Refresh='.mt_rand(10000,99999)); + } + + /* Delete file from server */ + hesk_unlink(HESK_PATH.$hesk_settings['attach_dir'].'/'.$att['saved_name']); + + /* Delete attachment from database */ + hesk_dbQuery("DELETE FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."attachments` WHERE `att_id`='".intval($att_id)."'"); + + hesk_process_messages($hesklang['kb_att_rem'],'admin_ticket.php?track='.$trackingID.'&Refresh='.mt_rand(10000,99999),'SUCCESS'); +} + + if (isset($_POST['note_message'])) { $n = $_POST['note_id']; if ($can_del_notes) @@ -891,8 +930,9 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php'); $noteAttachmentRS = hesk_dbQuery("SELECT `att_id`, `real_name`, `note_id` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."attachments` WHERE `note_id` = ".intval($note['id'])); while ($noteAttachment = hesk_dbFetchAssoc($noteAttachmentRS)) { - echo ' - '.$noteAttachment['real_name'].'
    '; + echo ' + + '.$noteAttachment['real_name'].'
    '; } ?>
    From 64f6be511c2e987040c06eaaeddd59fff920002e Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sat, 29 Nov 2014 14:13:00 -0500 Subject: [PATCH 143/208] Closes #83 now use Mods for Hesk instead of NuMods --- admin/admin_settings.php | 56 +++++++++---------- admin/admin_settings_save.php | 46 +++++++-------- css/hesk_newStyle.php | 24 ++++---- css/hesk_newStyleRTL.php | 24 ++++---- inc/header.inc.php | 10 ++-- inc/headerAdmin.inc.php | 10 ++-- install/index.php | 4 +- install/install_functions.inc.php | 2 +- ...updateNuMods.php => updateModsForHesk.php} | 11 ++-- language/en/text.php | 18 +++--- maintenance.php | 4 +- modsForHesk_settings.inc.php | 26 +++++++++ nuMods_settings.inc.php | 26 --------- print.php | 4 +- 14 files changed, 131 insertions(+), 134 deletions(-) rename install/{updateNuMods.php => updateModsForHesk.php} (81%) create mode 100644 modsForHesk_settings.inc.php delete mode 100644 nuMods_settings.inc.php diff --git a/admin/admin_settings.php b/admin/admin_settings.php index 6a4e52bd..d9f64de2 100644 --- a/admin/admin_settings.php +++ b/admin/admin_settings.php @@ -42,7 +42,7 @@ if (is_dir(HESK_PATH . 'install')) {die('Please delete the install folder // Get all the required files and functions require(HESK_PATH . 'hesk_settings.inc.php'); -require(HESK_PATH . 'nuMods_settings.inc.php'); +require(HESK_PATH . 'modsForHesk_settings.inc.php'); // Save the default language for the settings page before choosing user's preferred one $hesk_settings['language_default'] = $hesk_settings['language']; @@ -142,10 +142,10 @@ if ( defined('HESK_DEMO') )
    diff --git a/language/en/text.php b/language/en/text.php index f4c4174a..91b3ded9 100644 --- a/language/en/text.php +++ b/language/en/text.php @@ -21,6 +21,12 @@ $hesklang['_COLLATE']='utf8_unicode_ci'; // This is the email break line that will be used in email piping $hesklang['EMAIL_HR']='------ Reply above this line ------'; +// ADDED OR MODIFIED IN Mods For HESK 2.0.0 +$hesklang['date_custom_field'] = 'Date'; +$hesklang['time_custom_field'] = 'Time'; +$hesklang['datetime_custom_field'] = 'Date and time'; +$hesklang['multiple_select_custom_field'] = 'Multiple Select box'; + // ADDED OR MODIFIED IN Mods For HESK 1.6.0 $hesklang['ticket_closed'] = '[#%%TRACK_ID%%] Ticket closed/resolved'; $hesklang['ticket_reopen'] = '[#%%TRACK_ID%%] Ticket reopened'; From 46e09d618cfb3b5a3b503e5c3d00b172d95ee0ce Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 21 Dec 2014 23:57:14 -0500 Subject: [PATCH 166/208] #91 Add options text for the new custom field types --- .gitignore | 1 - admin/options.php | 329 +++++++++++++++++++++++++++++++++++++++++++ language/en/text.php | 4 + 3 files changed, 333 insertions(+), 1 deletion(-) create mode 100644 admin/options.php diff --git a/.gitignore b/.gitignore index 32828f4a..bdfa288b 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,6 @@ admin/archive.php admin/assign_owner.php admin/generate_spam_question.php admin/move_category.php -admin/options.php admin/priority.php admin/test_connection.php attachments/index.htm diff --git a/admin/options.php b/admin/options.php new file mode 100644 index 00000000..ca5d37f8 --- /dev/null +++ b/admin/options.php @@ -0,0 +1,329 @@ + + + + +<?php echo $hesklang['opt']; ?> + + + + + +

    + +

    + + + function hesk_saveOptions() + { + window.opener.document.getElementById(\'s_'.$id.'_val\').value = document.getElementById(\'o2\').value; + window.opener.document.getElementById(\'s_'.$id.'_maxlen\').value = document.getElementById(\'o1\').value; + window.close(); + } + +
    $myuser[name]$autoassign_code $edit_code $remove_code $activeMarkup
    :
    - : + : - +
    @@ -472,11 +472,11 @@ if ( defined('HESK_DEMO') )
  • - +
    From 1df1dfab48e995570ccafdf3be3d6027fc51a296 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sat, 29 Nov 2014 15:13:45 -0500 Subject: [PATCH 147/208] Update README for v1.6.0 --- README.md | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 013b73d1..29630cb8 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ [![Stories in Ready](https://badge.waffle.io/mkoch227/Mods-For-Hesk.png?label=waffle:ready&title=Ready)](https://waffle.io/mkoch227/Mods-For-Hesk) -

    NuMods v1.5.0

    +

    Mods for Hesk v1.6.0

    -This branch contains all files modified from the base version of HESK to become NuMods, a set of modifications for HESK v2.x +Mods for Hesk is a set of modifications for HESK v2.5.5, a free and popular helpdesk solution.

    Features

      @@ -18,11 +18,11 @@ This branch contains all files modified from the base version of HESK to become

      Download

      -You can download this mod via two ways: +You can download Mods for Hesk via two ways:
      1. Stable Releases: Releases that have a release tag associated with a commit are considered releases. You can click on "releases" on the top of the repo, and then click "zip" or "tar.gz" to download the repo at that stage.
      2. -
      3. Bleeding-edge Releases: You can also download the latest, bleeding-edge version of NuMods by simply clicking "download as zip" to the right of the repository. This will download an exact copy of this branch in its current state, which may be contain bugs/other issues. This is not recommended for a production use.
      4. +
      5. Bleeding-edge Releases: You can also download the latest, bleeding-edge version of Mods for Hesk by simply clicking "download as zip" to the right of the repository. This will download an exact copy of this branch in its current state, which may be contain bugs/other issues. This is not recommended for a production use.

      Installation

      @@ -30,18 +30,18 @@ You can download this mod via two ways:
      1. Download HESK from http://www.hesk.com/download.php.
      2. Extract the contents of HESK to a directory of your choice.
      3. -
      4. Download NuMods from one of the two methods described above.
      5. +
      6. Download Mods for Hesk from one of the two methods described above.
      7. Copy and paste the contents of the zip/tar.gz bundle and overwrite any files in the original HESK 2.x folder.
      8. Upload the resulting folder to your webserver.
      9. -
      10. Go to the /install directory in your web browser and click on "Install/Update NuMods Installation"
      11. +
      12. Go to the /install directory in your web browser and click on "Install/Update Mods for Hesk Installation"
      -

      Please consult the official HESK Documentation on how to install HESK, as it is the same for both HESK and NuMods.

      +

      Please consult the official HESK Documentation on how to install HESK, as it is the same for both HESK and Mods for Hesk.

      Languages

      -

      As of current, only English is a supported language, as there have been several language items that have been edited/created. If you want to translate NuMods to your own language, it is recommended to download the original HESK language file for your language, and then add/edit the lines listed under //Added or modified in HESK UI and //Added or modified in NuMods X.X.X (where X.X.X is a version number) for your language.

      -

      NuMods translations are available at http://numods.mkochcs.com/download.php.

      +

      As of current, only English is a supported language, as there have been several language items that have been edited/created. If you want to translate Mods for Hesk to your own language, it is recommended to download the original HESK language file for your language, and then add/edit the lines listed under //Added or modified in Mods for Hesk X.X.X (where X.X.X is a version number) for your language.

      +

      Mods for Hesk translations are available at http://mods-for-hesk.mkochcs.com/download.php.

      -

      Browser Compability

      +

      Browser Compatibility

      This list may be incomplete. Please leave a note on the PHP Junkyard forums for additional browser compatibility information.

      • Google Chrome 33+: Compatible
      • @@ -50,10 +50,10 @@ You can download this mod via two ways:
      • Internet Explorer 8: Partial Compatibility
      • Internet Explorer 9: Compatible
      -

      There are no intentions of making NuMods compatible with Internet Explorer 6 or 7, or any browser that is 2 or more major revisions older than its latest version.

      +

      There are no intentions of making Mods for Hesk compatible with Internet Explorer 6 or 7, or any browser that is 2 or more major revisions older than its latest version.

      Versioning

      -

      NuMods will be maintained under the Semantic Versioning guidelines as much as possible. Releases will be numbered with the following format:

      +

      Mods for Hesk will be maintained under the Semantic Versioning guidelines as much as possible. Releases will be numbered with the following format:

      <major>.<minor>.<patch> @@ -68,5 +68,5 @@ You can download this mod via two ways:

      For more information on SemVer, please visit http://semver.org.

      Credits

      -

      Mike Koch - Creator of NuMods

      +

      Mike Koch - Creator of Mods for Hesk

      Klemen Stirn - Creator of HESK

      From 41ad95ff89750782608c81bcf0f11400d3f16d16 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sat, 29 Nov 2014 20:37:44 -0500 Subject: [PATCH 148/208] Update README.md --- README.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 29630cb8..87c6e5d1 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ [![Stories in Ready](https://badge.waffle.io/mkoch227/Mods-For-Hesk.png?label=waffle:ready&title=Ready)](https://waffle.io/mkoch227/Mods-For-Hesk) -

      Mods for Hesk v1.6.0

      +

      Mods for HESK v1.6.0

      -Mods for Hesk is a set of modifications for HESK v2.5.5, a free and popular helpdesk solution. +Mods for HESK is a set of modifications for HESK v2.5.5, a free and popular helpdesk solution.

      Features

        @@ -18,11 +18,11 @@ Mods for Hesk is a set of modifications for HESK v2.5.5, a free and popular help

        Download

        -You can download Mods for Hesk via two ways: +You can download Mods for HESK via two ways:
        1. Stable Releases: Releases that have a release tag associated with a commit are considered releases. You can click on "releases" on the top of the repo, and then click "zip" or "tar.gz" to download the repo at that stage.
        2. -
        3. Bleeding-edge Releases: You can also download the latest, bleeding-edge version of Mods for Hesk by simply clicking "download as zip" to the right of the repository. This will download an exact copy of this branch in its current state, which may be contain bugs/other issues. This is not recommended for a production use.
        4. +
        5. Bleeding-edge Releases: You can also download the latest, bleeding-edge version of Mods for HESK by simply clicking "download as zip" to the right of the repository. This will download an exact copy of this branch in its current state, which may be contain bugs/other issues. This is not recommended for a production use.

        Installation

        @@ -30,16 +30,16 @@ You can download Mods for Hesk via two ways:
        1. Download HESK from http://www.hesk.com/download.php.
        2. Extract the contents of HESK to a directory of your choice.
        3. -
        4. Download Mods for Hesk from one of the two methods described above.
        5. +
        6. Download Mods for HESK from one of the two methods described above.
        7. Copy and paste the contents of the zip/tar.gz bundle and overwrite any files in the original HESK 2.x folder.
        8. Upload the resulting folder to your webserver.
        9. -
        10. Go to the /install directory in your web browser and click on "Install/Update Mods for Hesk Installation"
        11. +
        12. Go to the /install directory in your web browser and click on "Install/Update Mods for HESK Installation"
        -

        Please consult the official HESK Documentation on how to install HESK, as it is the same for both HESK and Mods for Hesk.

        +

        Please consult the official HESK Documentation on how to install HESK, as it is the same for both HESK and Mods for HESK.

        Languages

        -

        As of current, only English is a supported language, as there have been several language items that have been edited/created. If you want to translate Mods for Hesk to your own language, it is recommended to download the original HESK language file for your language, and then add/edit the lines listed under //Added or modified in Mods for Hesk X.X.X (where X.X.X is a version number) for your language.

        -

        Mods for Hesk translations are available at http://mods-for-hesk.mkochcs.com/download.php.

        +

        As of current, only English is a supported language, as there have been several language items that have been edited/created. If you want to translate Mods for HESK to your own language, it is recommended to download the original HESK language file for your language, and then add/edit the lines listed under //Added or modified in Mods for HESK X.X.X (where X.X.X is a version number) for your language.

        +

        Mods for HESK translations are available at http://mods-for-hesk.mkochcs.com/download.php.

        Browser Compatibility

        This list may be incomplete. Please leave a note on the PHP Junkyard forums for additional browser compatibility information. @@ -50,10 +50,10 @@ You can download Mods for Hesk via two ways:

      • Internet Explorer 8: Partial Compatibility
      • Internet Explorer 9: Compatible
      -

      There are no intentions of making Mods for Hesk compatible with Internet Explorer 6 or 7, or any browser that is 2 or more major revisions older than its latest version.

      +

      There are no intentions of making Mods for HESK compatible with Internet Explorer 6 or 7, or any browser that is 2 or more major revisions older than its latest version.

      Versioning

      -

      Mods for Hesk will be maintained under the Semantic Versioning guidelines as much as possible. Releases will be numbered with the following format:

      +

      Mods for HESK will be maintained under the Semantic Versioning guidelines as much as possible. Releases will be numbered with the following format:

      <major>.<minor>.<patch> @@ -68,5 +68,5 @@ You can download Mods for Hesk via two ways:

      For more information on SemVer, please visit http://semver.org.

      Credits

      -

      Mike Koch - Creator of Mods for Hesk

      +

      Mike Koch - Creator of Mods for HESK

      Klemen Stirn - Creator of HESK

      From 3aa10dfc4353565767d8fd90eb7e189759b552e2 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sat, 29 Nov 2014 21:03:50 -0500 Subject: [PATCH 149/208] Updated version numbers --- install/index.php | 4 ++-- install/install_functions.inc.php | 2 +- install/updateModsForHesk.php | 10 ++++++---- language/en/text.php | 18 +++++++++--------- 4 files changed, 18 insertions(+), 16 deletions(-) diff --git a/install/index.php b/install/index.php index 82b97f25..a02321e2 100644 --- a/install/index.php +++ b/install/index.php @@ -54,8 +54,8 @@ hesk_iHeader(); Upgrade


      Upgrade existing HESK installation to version



      - Install / Upgrade Mods for Hesk -


      Install or upgrade existing Mods for Hesk installation to version

      + Install / Upgrade Mods for HESK +


      Install or upgrade existing Mods for HESK installation to version

      - Mods For Hesk 1.5.0 Install / Upgrade + Mods For HESK 1.6.0 Install / Upgrade -

      Update Mods For Hesk from v1.4.1 to v1.5.0

      +

      Update Mods for HESK from v1.5.0 to v1.6.0

      +

      Update here. Do not use the installation below!

      +

      Update Mods For HESK from v1.4.1 to v1.5.0

      Update here. Do not use the installation below!

      -

      Update Mods For Hesk from v1.2.4 - v1.3.0 to v1.5.0

      +

      Update Mods For HESK from v1.2.4 - v1.3.0 to v1.5.0

      If you attempted the v1.4.0 installation and it failed, use this update link. Do not use the link below!

      Update here. Do not use the installation below!

      -

      Install Mods For Hesk v1.5.0 for the first time

      +

      Install Mods For HESK v1.5.0 for the first time

      If you have not yet installed/updated HESK, please do so first before continuing; otherwise installation will fail!


      Please verify the database information below. Additionally, ensure that the database user has CREATE and ALTER permissions.

      diff --git a/language/en/text.php b/language/en/text.php index a6812ea4..f4c4174a 100644 --- a/language/en/text.php +++ b/language/en/text.php @@ -21,7 +21,7 @@ $hesklang['_COLLATE']='utf8_unicode_ci'; // This is the email break line that will be used in email piping $hesklang['EMAIL_HR']='------ Reply above this line ------'; -// ADDED OR MODIFIED IN Mods For Hesk 1.6.0 +// ADDED OR MODIFIED IN Mods For HESK 1.6.0 $hesklang['ticket_closed'] = '[#%%TRACK_ID%%] Ticket closed/resolved'; $hesklang['ticket_reopen'] = '[#%%TRACK_ID%%] Ticket reopened'; $hesklang['ticket_reopen_assigned'] = '[#%%TRACK_ID%%] Assigned ticket reopened'; @@ -35,11 +35,11 @@ $hesklang['add_row'] = 'Add row'; $hesklang['addnote'] = 'Add note'; $hesklang['no_noteID'] = 'No Note ID'; $hesklang['note_id_not_found'] = 'Note ID not found'; -$hesklang['mods_for_hesk'] = 'Mods for Hesk'; +$hesklang['mods_for_hesk'] = 'Mods for HESK'; $hesklang['err_modsForHesk_settings'] = 'Can\'t open file modsForHesk_settings.inc.php for writing. Please CHMOD this file to 666 (rw-rw-rw-)'; -$hesklang['mods_for_hesk_version'] = 'Mods for Hesk Version'; +$hesklang['mods_for_hesk_version'] = 'Mods for HESK Version'; -// ADDED OR MODIFIED IN Mods For Hesk 1.5.0 +// ADDED OR MODIFIED IN Mods For HESK 1.5.0 $hesklang['ticket_auto_refresh'] = 'Ticket Table Auto-Refresh:'; $hesklang['display_rtl'] = 'Display site right-to-left'; $hesklang['show_icons_navigation'] = 'Show icons on navigation bar'; @@ -57,7 +57,7 @@ $hesklang['notify_customer_email_text'] = 'Don\'t send email notifications of re $hesklang['cant_edit_admin'] = 'You cannot edit the God Admin (User ID = 1)'; $hesklang['notifications_disabled_info'] = 'Changing notifications settings has been disabled by your administrator.'; -// ADDED OR MODIFIED IN Mods For Hesk 1.4.0 +// ADDED OR MODIFIED IN Mods For HESK 1.4.0 $hesklang['navbarBackgroundColor'] = 'Navbar Background Color'; $hesklang['navbarBackgroundColorHelp'] = 'The main color of the top navigation bar. This applies to both the client and staff-side.'; $hesklang['navbarBrandColor'] = 'Navbar Brand Color'; @@ -106,14 +106,14 @@ $hesklang['relationship_deleted'] = 'Parent/Child relationship deleted.'; $hesklang['autorefresh'] = 'Autorefresh:'; $hesklang['autorefresh_restrictions'] = 'Enter value in milliseconds. Value must be greater than 1000 to use this feature. No fractional values.'; -// ADDED OR MODIFIED IN Mods For Hesk 1.3.0 +// ADDED OR MODIFIED IN Mods For HESK 1.3.0 $hesklang['show_filters'] = 'Show Column Filters'; $hesklang['hide_filters'] = 'Hide Column Filters'; -// ADDED OR MODIFIED IN Mods For Hesk 1.2.2 +// ADDED OR MODIFIED IN Mods For HESK 1.2.2 $hesklang['changeLanguage'] = 'Change language to'; -// ADDED OR MODIFIED IN Mods For Hesk 1.2 +// ADDED OR MODIFIED IN Mods For HESK 1.2 $hesklang['statuses'] = 'Statuses'; $hesklang['basicProperties'] = 'Basic Properties'; $hesklang['shortNameKey'] = 'Short Name Key'; @@ -146,7 +146,7 @@ $hesklang['resolved']='Resolved'; // Ticket has been RESOLVED $hesklang['quick_help_ticket']='Here is the information on your ticket. You can add a reply to this ticket, close it, or re-open the ticket if applicable.'; -// ADDED OR MODIFIED IN Mods For Hesk pre-1.2 +// ADDED OR MODIFIED IN Mods For HESK pre-1.2 $hesklang['search_the_knowledgebase'] = 'Search the Knowledgebase'; $hesklang['view_ticket_nav']='View Ticket'; $hesklang['quick_help']='Quick Help'; From 33ec8ac79aba3540888a1153e7b5ed7f88feee49 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sat, 29 Nov 2014 21:28:51 -0500 Subject: [PATCH 150/208] Hopefully making the installation script easier to run --- install/updateModsForHesk.php | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/install/updateModsForHesk.php b/install/updateModsForHesk.php index d0343a4c..18b6b301 100644 --- a/install/updateModsForHesk.php +++ b/install/updateModsForHesk.php @@ -9,23 +9,22 @@ require(HESK_PATH . 'hesk_settings.inc.php'); Mods For HESK 1.6.0 Install / Upgrade -

      Update Mods for HESK from v1.5.0 to v1.6.0

      -

      Update here. Do not use the installation below!

      -

      Update Mods For HESK from v1.4.1 to v1.5.0

      -

      Update here. Do not use the installation below!

      -

      Update Mods For HESK from v1.2.4 - v1.3.0 to v1.5.0

      -

      If you attempted the v1.4.0 installation and it failed, use this update link. Do not use the link below!

      -

      Update here. Do not use the installation below!

      -

      Install Mods For HESK v1.5.0 for the first time

      -

      If you have not yet installed/updated HESK, please do so first before continuing; otherwise installation will fail!

      -
      +

      Mods for HESK 1.6.0 Install / Upgrade

      +

      Select your current Mods for HESK version number to upgrade.

      +

      Please verify the database information below. Additionally, ensure that the database user has CREATE and ALTER permissions.

      Database Host:

      Database Name:

      Database User:

      Database Password:

      Database Prefix:

      - Proceed with installation +

      By proceeding, you agree to the terms of the Creative Commons Attribution-ShareAlike 4.0 International License.

      From 6d7a075d5b0abce373e0ed1883ca19297ecfa421 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sat, 29 Nov 2014 21:35:11 -0500 Subject: [PATCH 151/208] Fix link and text. How did I miss this for so long??? --- install/install.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install/install.php b/install/install.php index e204121d..bf31bbb1 100644 --- a/install/install.php +++ b/install/install.php @@ -170,7 +170,7 @@ function hesk_iFinish()
      Success! HESK Successfully installed
      Next Steps:

        -
      1. Don't forget to run the NuHesk Installation!
      2. +
      3. Don't forget to run the Mods for HESK Installation!
      4. Remember your login details:
        
        From f339dbc2ba076dd86755f52aaa22b344b587213b Mon Sep 17 00:00:00 2001
        From: Mike Koch 
        Date: Sat, 29 Nov 2014 21:51:07 -0500
        Subject: [PATCH 152/208] Wrap each link an 
      5. tag --- install/updateModsForHesk.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/install/updateModsForHesk.php b/install/updateModsForHesk.php index 18b6b301..9a07e69a 100644 --- a/install/updateModsForHesk.php +++ b/install/updateModsForHesk.php @@ -12,11 +12,11 @@ require(HESK_PATH . 'hesk_settings.inc.php');

        Mods for HESK 1.6.0 Install / Upgrade

        Select your current Mods for HESK version number to upgrade.

        Please verify the database information below. Additionally, ensure that the database user has CREATE and ALTER permissions.

        Database Host:

        From d26ed0bac199c67a987f8422eda094e1c1fef288 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sat, 29 Nov 2014 22:10:57 -0500 Subject: [PATCH 153/208] Run the query before hiding specific fields in demo mode --- admin/admin_settings.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/admin/admin_settings.php b/admin/admin_settings.php index 0f011aee..43f64562 100644 --- a/admin/admin_settings.php +++ b/admin/admin_settings.php @@ -77,6 +77,10 @@ require_once(HESK_PATH . 'inc/headerAdmin.inc.php'); // Print main manage users page require_once(HESK_PATH . 'inc/show_admin_nav.inc.php'); +// Get the current version of Mods for Hesk +$modsForHeskVersionRS = hesk_dbQuery("SELECT `Value` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."settings` WHERE `Key` = 'modsForHeskVersion'"); +$modsForHeskVersion = hesk_dbFetchAssoc($modsForHeskVersionRS)['Value']; + // Demo mode? Hide values of sensitive settings if ( defined('HESK_DEMO') ) { @@ -95,9 +99,6 @@ if ( defined('HESK_DEMO') ) $hesk_settings['recaptcha_private_key'] = $hesklang['hdemo']; } -// Get the current version of Mods for Hesk -$modsForHeskVersionRS = hesk_dbQuery("SELECT `Value` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."settings` WHERE `Key` = 'modsForHeskVersion'"); -$modsForHeskVersion = hesk_dbFetchAssoc($modsForHeskVersionRS)['Value']; ?>
        From 8ed533ecada7e041e864491b559958de97f2943d Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sat, 29 Nov 2014 22:14:13 -0500 Subject: [PATCH 154/208] Forgot to rename JavaScript file --- js/{nuMods-javascript.js => modsForHesk-javascript.js} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename js/{nuMods-javascript.js => modsForHesk-javascript.js} (100%) diff --git a/js/nuMods-javascript.js b/js/modsForHesk-javascript.js similarity index 100% rename from js/nuMods-javascript.js rename to js/modsForHesk-javascript.js From 4b0a40ceaa2bd2e2ae15985fb9a87f8deb35a06f Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sat, 29 Nov 2014 23:59:25 -0500 Subject: [PATCH 155/208] Fix demo mode for the MFH demo site --- admin/admin_settings.php | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/admin/admin_settings.php b/admin/admin_settings.php index 43f64562..6dd7c6b6 100644 --- a/admin/admin_settings.php +++ b/admin/admin_settings.php @@ -84,11 +84,6 @@ $modsForHeskVersion = hesk_dbFetchAssoc($modsForHeskVersionRS)['Value']; // Demo mode? Hide values of sensitive settings if ( defined('HESK_DEMO') ) { - $hesk_settings['db_host'] = $hesklang['hdemo']; - $hesk_settings['db_name'] = $hesklang['hdemo']; - $hesk_settings['db_user'] = $hesklang['hdemo']; - $hesk_settings['db_pass'] = $hesklang['hdemo']; - $hesk_settings['db_pfix'] = $hesklang['hdemo']; $hesk_settings['smtp_host_name'] = $hesklang['hdemo']; $hesk_settings['smtp_user'] = $hesklang['hdemo']; $hesk_settings['smtp_password'] = $hesklang['hdemo']; @@ -557,31 +552,31 @@ if ( defined('HESK_DEMO') )
        - +
        - +
        - +
        - +
        - +
        From 8d3a66ded8c6e60f15810e3e60a53bb9a8c10928 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Wed, 3 Dec 2014 07:02:58 -0500 Subject: [PATCH 156/208] Fix version number retrieval for PHP versions before 5.5 --- admin/admin_settings.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/admin/admin_settings.php b/admin/admin_settings.php index 6dd7c6b6..a0899dd4 100644 --- a/admin/admin_settings.php +++ b/admin/admin_settings.php @@ -79,7 +79,8 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php'); // Get the current version of Mods for Hesk $modsForHeskVersionRS = hesk_dbQuery("SELECT `Value` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."settings` WHERE `Key` = 'modsForHeskVersion'"); -$modsForHeskVersion = hesk_dbFetchAssoc($modsForHeskVersionRS)['Value']; +$modsForHeskVersionArray = hesk_dbFetchAssoc($modsForHeskVersionRS); +$modsForHeskVersion = $modsForHeskVersionArray['Value']; // Demo mode? Hide values of sensitive settings if ( defined('HESK_DEMO') ) From 8d81ed5ebd03d8ffe6a850fb9941f3af638639db Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Wed, 3 Dec 2014 07:14:15 -0500 Subject: [PATCH 157/208] Update version number --- README.md | 2 +- install/updateTo1-6-0.php | 4 +--- install/updateTo1-6-1.php | 11 +++++++++++ 3 files changed, 13 insertions(+), 4 deletions(-) create mode 100644 install/updateTo1-6-1.php diff --git a/README.md b/README.md index 87c6e5d1..c6e37e35 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ [![Stories in Ready](https://badge.waffle.io/mkoch227/Mods-For-Hesk.png?label=waffle:ready&title=Ready)](https://waffle.io/mkoch227/Mods-For-Hesk) -

        Mods for HESK v1.6.0

        +

        Mods for HESK v1.6.1

        Mods for HESK is a set of modifications for HESK v2.5.5, a free and popular helpdesk solution. diff --git a/install/updateTo1-6-0.php b/install/updateTo1-6-0.php index d3740fef..bf1d0184 100644 --- a/install/updateTo1-6-0.php +++ b/install/updateTo1-6-0.php @@ -12,7 +12,5 @@ hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."attachmen hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."attachments` MODIFY COLUMN `ticket_id` VARCHAR(13) NULL"); hesk_dbQuery("CREATE TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."settings` (`Key` NVARCHAR(200) NOT NULL, `Value` NVARCHAR(200) NOT NULL)"); hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."settings` (`Key`, `Value`) VALUES ('modsForHeskVersion', '1.6.0')"); -?> -

        Installation / Update complete!

        -

        Please delete the install folder for security reasons, and then proceed back to the Help Desk

        \ No newline at end of file +header('Location: update-to1-6-1.php'); \ No newline at end of file diff --git a/install/updateTo1-6-1.php b/install/updateTo1-6-1.php new file mode 100644 index 00000000..359edddf --- /dev/null +++ b/install/updateTo1-6-1.php @@ -0,0 +1,11 @@ + + +

        Installation / Update complete!

        +

        Please delete the install folder for security reasons, and then proceed back to the Help Desk

        \ No newline at end of file From 4dc767855ad546af29077771d99ee1852458a10c Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Wed, 3 Dec 2014 07:16:28 -0500 Subject: [PATCH 158/208] Update install file --- install/updateModsForHesk.php | 1 + 1 file changed, 1 insertion(+) diff --git a/install/updateModsForHesk.php b/install/updateModsForHesk.php index 9a07e69a..3503a673 100644 --- a/install/updateModsForHesk.php +++ b/install/updateModsForHesk.php @@ -12,6 +12,7 @@ require(HESK_PATH . 'hesk_settings.inc.php');

        Mods for HESK 1.6.0 Install / Upgrade

        Select your current Mods for HESK version number to upgrade.

          +
        • v1.6.0
        • v1.5.0
        • v1.4.1
        • v1.4.0
        • From 16fc6dea868a278ee5cb635660c83fb431219396 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 7 Dec 2014 00:04:15 -0500 Subject: [PATCH 159/208] #88 Remove maintenance mode feature --- admin/admin_settings.php | 14 -------------- admin/admin_settings_save.php | 6 +----- admin/index.php | 1 - inc/header.inc.php | 4 ---- maintenance.php | 24 ------------------------ modsForHesk_settings.inc.php | 5 +---- 6 files changed, 2 insertions(+), 52 deletions(-) delete mode 100644 maintenance.php diff --git a/admin/admin_settings.php b/admin/admin_settings.php index a0899dd4..4ac24a06 100644 --- a/admin/admin_settings.php +++ b/admin/admin_settings.php @@ -1817,20 +1817,6 @@ if ( defined('HESK_DEMO') )
        -
        - -
        -
        - -
        -
        -
        diff --git a/admin/admin_settings_save.php b/admin/admin_settings_save.php index d409ba78..bb29ae1c 100644 --- a/admin/admin_settings_save.php +++ b/admin/admin_settings_save.php @@ -537,7 +537,6 @@ $set['hesk_version'] = $hesk_settings['hesk_version']; // Save the modsForHesk_settings.inc.php file $set['rtl'] = empty($_POST['rtl']) ? 0 : 1; $set['show-icons'] = empty($_POST['show-icons']) ? 0 : 1; -$set['maintenance-mode'] = empty($_POST['maintenance-mode']) ? 0 : 1; $set['navbarBackgroundColor'] = hesk_input(hesk_POST('navbarBackgroundColor')); $set['navbarBrandColor'] = hesk_input(hesk_POST('navbarBrandColor')); $set['navbarBrandHoverColor'] = hesk_input(hesk_POST('navbarBrandHoverColor')); @@ -568,10 +567,7 @@ $modsForHesk_settings[\'questionMarkColor\'] = \''.$set['questionMarkColor'].'\' $modsForHesk_settings[\'rtl\'] = '.$set['rtl'].'; //-- Set this to 1 to show icons next to navigation menu items -$modsForHesk_settings[\'show_icons\'] = '.$set['show-icons'].'; - -//-- Set this to 1 to enable maintenance mode -$modsForHesk_settings[\'maintenance_mode\'] = '.$set['maintenance-mode'].';'; +$modsForHesk_settings[\'show_icons\'] = '.$set['show-icons'].';'; // Write the file if ( ! file_put_contents(HESK_PATH . 'modsForHesk_settings.inc.php', $modsForHesk_file_content) ) diff --git a/admin/index.php b/admin/index.php index f23f0ffe..25f222b6 100644 --- a/admin/index.php +++ b/admin/index.php @@ -34,7 +34,6 @@ define('IN_SCRIPT',1); define('HESK_PATH','../'); -define('ON_LOGIN_PAGE',1); /* Get all the required files and functions */ require(HESK_PATH . 'hesk_settings.inc.php'); diff --git a/inc/header.inc.php b/inc/header.inc.php index 90b4810e..70375a1a 100644 --- a/inc/header.inc.php +++ b/inc/header.inc.php @@ -35,10 +35,6 @@ /* Check if this is a valid include */ if (!defined('IN_SCRIPT')) {die('Invalid attempt');} require(HESK_PATH . 'modsForHesk_settings.inc.php'); -// Check to see if we're in maintenance mode before sending anything to the DOM -if ($modsForHesk_settings['maintenance_mode'] && !defined('ON_MAINTENANCE_PAGE') && !defined('ON_LOGIN_PAGE')) { - header('Location: '.HESK_PATH.'maintenance.php'); -} ?> diff --git a/maintenance.php b/maintenance.php deleted file mode 100644 index 0037c119..00000000 --- a/maintenance.php +++ /dev/null @@ -1,24 +0,0 @@ - -
        -
        -
        -

        The helpdesk is currently undergoing maintenance. Please come back later.

        -
        -
        - \ No newline at end of file diff --git a/modsForHesk_settings.inc.php b/modsForHesk_settings.inc.php index fa9c9135..2d9a5780 100644 --- a/modsForHesk_settings.inc.php +++ b/modsForHesk_settings.inc.php @@ -17,7 +17,4 @@ $modsForHesk_settings['questionMarkColor'] = '#000000'; $modsForHesk_settings['rtl'] = 0; //-- Set this to 1 to show icons next to navigation menu items -$modsForHesk_settings['show_icons'] = 0; - -//-- Set this to 1 to enable maintenance mode -$modsForHesk_settings['maintenance_mode'] = 0; \ No newline at end of file +$modsForHesk_settings['show_icons'] = 0; \ No newline at end of file From f61c05ac34f3ebf0067de022a30c88564846b4dc Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 7 Dec 2014 00:07:59 -0500 Subject: [PATCH 160/208] #88 Remove WHOIS lookup capabilities --- admin/admin_ticket.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/admin_ticket.php b/admin/admin_ticket.php index 64b9bef9..a55e8985 100644 --- a/admin/admin_ticket.php +++ b/admin/admin_ticket.php @@ -1020,7 +1020,7 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
        -
        : '.$ticket['ip'].''; ?>
        +
        :
        From 21781b20c7022cea3dbe04902750190f2e125d45 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Mon, 8 Dec 2014 21:14:12 -0500 Subject: [PATCH 161/208] Closes #89 selected from wrong table hame --- admin/delete_tickets.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/delete_tickets.php b/admin/delete_tickets.php index c68b10d6..5403e9fa 100644 --- a/admin/delete_tickets.php +++ b/admin/delete_tickets.php @@ -243,7 +243,7 @@ else hesk_okCategory($ticket['category']); - $closedStatusRS = hesk_dbQuery("SELECT * FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` WHERE `IsStaffClosedOption` = 1"); + $closedStatusRS = hesk_dbQuery("SELECT * FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."statuses` WHERE `IsStaffClosedOption` = 1"); $closedStatus = hesk_dbFetchAssoc($closedStatusRS); hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` SET `status`='".$closedStatus['ID']."', `history`=CONCAT(`history`,'".hesk_dbEscape($revision)."') WHERE `id`='".intval($this_id)."' LIMIT 1"); From 0924dd5cc88cf33b9a459f1f0e8b57601698d367 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 14 Dec 2014 23:36:21 -0500 Subject: [PATCH 162/208] Revert the removal of some features...for now This reverts commit f61c05ac34f3ebf0067de022a30c88564846b4dc. --- admin/admin_settings.php | 14 ++++++++++++++ admin/admin_settings_save.php | 6 +++++- admin/admin_ticket.php | 2 +- admin/index.php | 1 + inc/header.inc.php | 4 ++++ maintenance.php | 24 ++++++++++++++++++++++++ modsForHesk_settings.inc.php | 5 ++++- 7 files changed, 53 insertions(+), 3 deletions(-) create mode 100644 maintenance.php diff --git a/admin/admin_settings.php b/admin/admin_settings.php index 4ac24a06..a0899dd4 100644 --- a/admin/admin_settings.php +++ b/admin/admin_settings.php @@ -1817,6 +1817,20 @@ if ( defined('HESK_DEMO') )
        +
        + +
        +
        + +
        +
        +
        diff --git a/admin/admin_settings_save.php b/admin/admin_settings_save.php index bb29ae1c..d409ba78 100644 --- a/admin/admin_settings_save.php +++ b/admin/admin_settings_save.php @@ -537,6 +537,7 @@ $set['hesk_version'] = $hesk_settings['hesk_version']; // Save the modsForHesk_settings.inc.php file $set['rtl'] = empty($_POST['rtl']) ? 0 : 1; $set['show-icons'] = empty($_POST['show-icons']) ? 0 : 1; +$set['maintenance-mode'] = empty($_POST['maintenance-mode']) ? 0 : 1; $set['navbarBackgroundColor'] = hesk_input(hesk_POST('navbarBackgroundColor')); $set['navbarBrandColor'] = hesk_input(hesk_POST('navbarBrandColor')); $set['navbarBrandHoverColor'] = hesk_input(hesk_POST('navbarBrandHoverColor')); @@ -567,7 +568,10 @@ $modsForHesk_settings[\'questionMarkColor\'] = \''.$set['questionMarkColor'].'\' $modsForHesk_settings[\'rtl\'] = '.$set['rtl'].'; //-- Set this to 1 to show icons next to navigation menu items -$modsForHesk_settings[\'show_icons\'] = '.$set['show-icons'].';'; +$modsForHesk_settings[\'show_icons\'] = '.$set['show-icons'].'; + +//-- Set this to 1 to enable maintenance mode +$modsForHesk_settings[\'maintenance_mode\'] = '.$set['maintenance-mode'].';'; // Write the file if ( ! file_put_contents(HESK_PATH . 'modsForHesk_settings.inc.php', $modsForHesk_file_content) ) diff --git a/admin/admin_ticket.php b/admin/admin_ticket.php index a55e8985..64b9bef9 100644 --- a/admin/admin_ticket.php +++ b/admin/admin_ticket.php @@ -1020,7 +1020,7 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
        -
        :
        +
        : '.$ticket['ip'].''; ?>
        diff --git a/admin/index.php b/admin/index.php index 25f222b6..f23f0ffe 100644 --- a/admin/index.php +++ b/admin/index.php @@ -34,6 +34,7 @@ define('IN_SCRIPT',1); define('HESK_PATH','../'); +define('ON_LOGIN_PAGE',1); /* Get all the required files and functions */ require(HESK_PATH . 'hesk_settings.inc.php'); diff --git a/inc/header.inc.php b/inc/header.inc.php index 70375a1a..90b4810e 100644 --- a/inc/header.inc.php +++ b/inc/header.inc.php @@ -35,6 +35,10 @@ /* Check if this is a valid include */ if (!defined('IN_SCRIPT')) {die('Invalid attempt');} require(HESK_PATH . 'modsForHesk_settings.inc.php'); +// Check to see if we're in maintenance mode before sending anything to the DOM +if ($modsForHesk_settings['maintenance_mode'] && !defined('ON_MAINTENANCE_PAGE') && !defined('ON_LOGIN_PAGE')) { + header('Location: '.HESK_PATH.'maintenance.php'); +} ?> diff --git a/maintenance.php b/maintenance.php new file mode 100644 index 00000000..0037c119 --- /dev/null +++ b/maintenance.php @@ -0,0 +1,24 @@ + +
        +
        +
        +

        The helpdesk is currently undergoing maintenance. Please come back later.

        +
        +
        + \ No newline at end of file diff --git a/modsForHesk_settings.inc.php b/modsForHesk_settings.inc.php index 2d9a5780..fa9c9135 100644 --- a/modsForHesk_settings.inc.php +++ b/modsForHesk_settings.inc.php @@ -17,4 +17,7 @@ $modsForHesk_settings['questionMarkColor'] = '#000000'; $modsForHesk_settings['rtl'] = 0; //-- Set this to 1 to show icons next to navigation menu items -$modsForHesk_settings['show_icons'] = 0; \ No newline at end of file +$modsForHesk_settings['show_icons'] = 0; + +//-- Set this to 1 to enable maintenance mode +$modsForHesk_settings['maintenance_mode'] = 0; \ No newline at end of file From 1ae552f02a8b868c2a40bc2419592762711fe305 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 14 Dec 2014 23:42:49 -0500 Subject: [PATCH 163/208] Closes #90 Fix the redirect to updateTo1-6-1 --- install/updateTo1-6-0.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install/updateTo1-6-0.php b/install/updateTo1-6-0.php index bf1d0184..616ebb48 100644 --- a/install/updateTo1-6-0.php +++ b/install/updateTo1-6-0.php @@ -13,4 +13,4 @@ hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."attachmen hesk_dbQuery("CREATE TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."settings` (`Key` NVARCHAR(200) NOT NULL, `Value` NVARCHAR(200) NOT NULL)"); hesk_dbQuery("INSERT INTO `".hesk_dbEscape($hesk_settings['db_pfix'])."settings` (`Key`, `Value`) VALUES ('modsForHeskVersion', '1.6.0')"); -header('Location: update-to1-6-1.php'); \ No newline at end of file +header('Location: updateTo1-6-1.php'); \ No newline at end of file From 23b68707ec1630046f2b060d0fa3b28612ebd2bf Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 14 Dec 2014 23:53:06 -0500 Subject: [PATCH 164/208] Closes #93 Show the language dropdown on the header --- inc/header.inc.php | 6 ++++++ index.php | 10 ---------- ticket.php | 10 ---------- 3 files changed, 6 insertions(+), 20 deletions(-) diff --git a/inc/header.inc.php b/inc/header.inc.php index 90b4810e..6bf1f328 100644 --- a/inc/header.inc.php +++ b/inc/header.inc.php @@ -167,6 +167,12 @@ if ($modsForHesk_settings['show_icons']) {
      6. > 
    + + + + diff --git a/index.php b/index.php index 7e559085..2ea4464f 100644 --- a/index.php +++ b/index.php @@ -106,16 +106,6 @@ function print_add_ticket()
    - -
    -
    - -
    -
    - -
    -
    -

    diff --git a/ticket.php b/ticket.php index fe6cc0a5..2ac6e220 100644 --- a/ticket.php +++ b/ticket.php @@ -212,16 +212,6 @@ require_once(HESK_PATH . 'inc/header.inc.php');
    - -
    -
    - -
    -
    - -
    -
    -

    From 73be89c4724b8122b466a7fbfbb53f9c05f2de47 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Sun, 21 Dec 2014 23:41:56 -0500 Subject: [PATCH 165/208] #91 Add new custom field options to settings dropdown --- admin/admin_settings.php | 4 ++++ language/en/text.php | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/admin/admin_settings.php b/admin/admin_settings.php index a0899dd4..4a2d2184 100644 --- a/admin/admin_settings.php +++ b/admin/admin_settings.php @@ -1238,6 +1238,10 @@ if ( defined('HESK_DEMO') ) + + + +
    + + + + + + +
    '.$hesklang['custom_l'].': +
    '.$hesklang['defw'].': +
    +

    + '; + break; + case 'textarea': + if (strpos($query,'#') !== false) + { + list($rows,$cols)=explode('#',$query); + } + else + { + $rows = ''; + $cols = ''; + } + echo ' + + + + + + + + +
    '.$hesklang['rows'].': +
    '.$hesklang['cols'].': +
    +

    + '; + break; + case 'radio': + $options=str_replace('#HESK#',"\n",$query); + echo ' + + +

    '.$hesklang['opt2'].'

    + +

    + '; + break; + case 'select': + $options=str_replace('#HESK#',"\n",$query); + echo ' + + +

    '.$hesklang['opt3'].'

    + +

    + '; + break; + case 'checkbox': + $options=str_replace('#HESK#',"\n",$query); + echo ' + + +

    '.$hesklang['opt4'].'

    + +

    + '; + break; + case 'date': + echo '

    '.$hesklang['date_custom_field_text'].'

    '; + break; + case 'time': + echo '

    '.$hesklang['time_custom_field_text'].'

    '; + break; + case 'datetime': + echo '

    '.$hesklang['datetime_custom_field_text'].'

    '; + break; + case 'multiselect': + $options=str_replace('#HESK#',"\n",$query); + echo ' + + +

    '.$hesklang['multiple_select_custom_field_text'].'

    + +

    + '; + break; + default: + die('Invalid type'); +} +?> + +

    + +

     

    + + + + + diff --git a/language/en/text.php b/language/en/text.php index 91b3ded9..335dbc63 100644 --- a/language/en/text.php +++ b/language/en/text.php @@ -23,9 +23,13 @@ $hesklang['EMAIL_HR']='------ Reply above this line ------'; // ADDED OR MODIFIED IN Mods For HESK 2.0.0 $hesklang['date_custom_field'] = 'Date'; +$hesklang['date_custom_field_text'] = 'No options for this custom field type.'; $hesklang['time_custom_field'] = 'Time'; +$hesklang['time_custom_field_text'] = 'No options for this custom field type.'; $hesklang['datetime_custom_field'] = 'Date and time'; +$hesklang['datetime_custom_field_text'] = 'No options for this custom field type.'; $hesklang['multiple_select_custom_field'] = 'Multiple Select box'; +$hesklang['multiple_select_custom_field_text'] = 'Options for this multi-select box, enter one option per line (each line will be a choice your customers can choose from). You need to enter at least two options!'; // ADDED OR MODIFIED IN Mods For HESK 1.6.0 $hesklang['ticket_closed'] = '[#%%TRACK_ID%%] Ticket closed/resolved'; From 50f5ce45966f64b92a02b4d4553d1653fad7032a Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Mon, 22 Dec 2014 00:12:13 -0500 Subject: [PATCH 167/208] #91 Add new custom field options to the array of possible choices --- admin/admin_settings.php | 2 -- admin/admin_settings_save.php | 2 +- admin/options.php | 6 ------ language/en/text.php | 4 ---- 4 files changed, 1 insertion(+), 13 deletions(-) diff --git a/admin/admin_settings.php b/admin/admin_settings.php index 4a2d2184..e823f8e8 100644 --- a/admin/admin_settings.php +++ b/admin/admin_settings.php @@ -1239,8 +1239,6 @@ if ( defined('HESK_DEMO') ) - - diff --git a/admin/admin_settings_save.php b/admin/admin_settings_save.php index d409ba78..4f26f76b 100644 --- a/admin/admin_settings_save.php +++ b/admin/admin_settings_save.php @@ -390,7 +390,7 @@ for ($i=1;$i<=20;$i++) $set['custom_fields'][$this_field]['maxlen'] = intval( hesk_POST('s_custom'.$i.'_maxlen', 255) ); $set['custom_fields'][$this_field]['value'] = hesk_input( hesk_POST('s_custom'.$i.'_val') ); - if (!in_array($set['custom_fields'][$this_field]['type'],array('text','textarea','select','radio','checkbox'))) + if (!in_array($set['custom_fields'][$this_field]['type'],array('text','textarea','select','radio','checkbox','date','multiselect'))) { $set['custom_fields'][$this_field]['type'] = 'text'; } diff --git a/admin/options.php b/admin/options.php index ca5d37f8..95d05481 100644 --- a/admin/options.php +++ b/admin/options.php @@ -268,12 +268,6 @@ switch ($type) case 'date': echo '

    '.$hesklang['date_custom_field_text'].'

    '; break; - case 'time': - echo '

    '.$hesklang['time_custom_field_text'].'

    '; - break; - case 'datetime': - echo '

    '.$hesklang['datetime_custom_field_text'].'

    '; - break; case 'multiselect': $options=str_replace('#HESK#',"\n",$query); echo ' diff --git a/language/en/text.php b/language/en/text.php index 335dbc63..9d281c77 100644 --- a/language/en/text.php +++ b/language/en/text.php @@ -24,10 +24,6 @@ $hesklang['EMAIL_HR']='------ Reply above this line ------'; // ADDED OR MODIFIED IN Mods For HESK 2.0.0 $hesklang['date_custom_field'] = 'Date'; $hesklang['date_custom_field_text'] = 'No options for this custom field type.'; -$hesklang['time_custom_field'] = 'Time'; -$hesklang['time_custom_field_text'] = 'No options for this custom field type.'; -$hesklang['datetime_custom_field'] = 'Date and time'; -$hesklang['datetime_custom_field_text'] = 'No options for this custom field type.'; $hesklang['multiple_select_custom_field'] = 'Multiple Select box'; $hesklang['multiple_select_custom_field_text'] = 'Options for this multi-select box, enter one option per line (each line will be a choice your customers can choose from). You need to enter at least two options!'; From e943e44f29426628b751f37fea7476648c678203 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Mon, 22 Dec 2014 00:30:21 -0500 Subject: [PATCH 168/208] #91 Support multi-select and date custom fields on new ticket page (admin) --- admin/new_ticket.php | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/admin/new_ticket.php b/admin/new_ticket.php index 84a0a323..096001f0 100644 --- a/admin/new_ticket.php +++ b/admin/new_ticket.php @@ -275,6 +275,33 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php'); echo '
    '; break; + case 'multiselect': + $cls = in_array($k,$_SESSION['iserror']) ? ' class="isError" ' : ''; + + echo '
    +
    '; + break; + /* Checkbox */ case 'checkbox': echo '
    '; @@ -312,6 +339,20 @@ require_once(HESK_PATH . 'inc/show_admin_nav.inc.php');
    '; break; + case 'date': + if (strlen($k_value) != 0) + { + $v['value'] = $k_value; + } + + $cls = in_array($k,$_SESSION['iserror']) ? ' class="isError" ' : ''; + + echo '
    + +
    +
    '; + break; + /* Default text input */ default: if (strlen($k_value) != 0) From 085d1b6d228a08bbbb03b53580ace6b7617dca79 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Mon, 22 Dec 2014 00:46:47 -0500 Subject: [PATCH 169/208] Multiselect is already working --- admin/admin_submit_ticket.php | 10 ++++++++++ language/en/text.php | 1 + 2 files changed, 11 insertions(+) diff --git a/admin/admin_submit_ticket.php b/admin/admin_submit_ticket.php index 8b229636..60cc2ff8 100644 --- a/admin/admin_submit_ticket.php +++ b/admin/admin_submit_ticket.php @@ -92,6 +92,16 @@ foreach ($hesk_settings['custom_fields'] as $k=>$v) { if ($v['use'] && isset($_POST[$k])) { + // Dates must be in YYYY-MM-DD format. Thanks to + // http://stackoverflow.com/questions/19773418/regex-to-validate-date-in-php-using-format-as-yyyy-mm-dd for the regex! + if( $v['type'] == 'date' && $_POST[$k] != '') + { + if (!preg_match('^(19|20)\d\d[\-\/.](0[1-9]|1[012])[\-\/.](0[1-9]|[12][0-9]|3[01])$', $_POST[$k]) || strtotime($_POST[$k]) < 0) + $hesk_error_buffer[$k]=$hesklang['invalid_date_format']; + } else { + $tmpvar[$k] = hesk_dateToString($_POST[$k]); + } + if (is_array($_POST[$k])) { $tmpvar[$k]=''; diff --git a/language/en/text.php b/language/en/text.php index 9d281c77..cb6e6414 100644 --- a/language/en/text.php +++ b/language/en/text.php @@ -26,6 +26,7 @@ $hesklang['date_custom_field'] = 'Date'; $hesklang['date_custom_field_text'] = 'No options for this custom field type.'; $hesklang['multiple_select_custom_field'] = 'Multiple Select box'; $hesklang['multiple_select_custom_field_text'] = 'Options for this multi-select box, enter one option per line (each line will be a choice your customers can choose from). You need to enter at least two options!'; +$hesklang['invalid_date_format'] = 'Date must be in YYYY-MM-DD format.'; // ADDED OR MODIFIED IN Mods For HESK 1.6.0 $hesklang['ticket_closed'] = '[#%%TRACK_ID%%] Ticket closed/resolved'; From f7064ed3994e365ae9d3d49d960fe94e4bd4edc9 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Wed, 24 Dec 2014 01:46:39 -0500 Subject: [PATCH 170/208] #91 Add jQuery UI --- css/jquery-ui.css | 1225 ++++++++++++++++++ css/jquery-ui.structure.css | 833 ++++++++++++ css/jquery-ui.theme.css | 410 ++++++ img/ui-bg_flat_0_aaaaaa_40x100.png | Bin 0 -> 212 bytes img/ui-bg_flat_75_ffffff_40x100.png | Bin 0 -> 208 bytes img/ui-bg_glass_55_fbf9ee_1x400.png | Bin 0 -> 335 bytes img/ui-bg_glass_65_ffffff_1x400.png | Bin 0 -> 207 bytes img/ui-bg_glass_75_dadada_1x400.png | Bin 0 -> 262 bytes img/ui-bg_glass_75_e6e6e6_1x400.png | Bin 0 -> 262 bytes img/ui-bg_glass_95_fef1ec_1x400.png | Bin 0 -> 332 bytes img/ui-bg_highlight-soft_75_cccccc_1x100.png | Bin 0 -> 280 bytes img/ui-icons_222222_256x240.png | Bin 0 -> 6922 bytes img/ui-icons_2e83ff_256x240.png | Bin 0 -> 4549 bytes img/ui-icons_454545_256x240.png | Bin 0 -> 6992 bytes img/ui-icons_888888_256x240.png | Bin 0 -> 6999 bytes img/ui-icons_cd0a0a_256x240.png | Bin 0 -> 4549 bytes inc/headerAdmin.inc.php | 4 + js/jquery-ui.min.js | 13 + 18 files changed, 2485 insertions(+) create mode 100644 css/jquery-ui.css create mode 100644 css/jquery-ui.structure.css create mode 100644 css/jquery-ui.theme.css create mode 100644 img/ui-bg_flat_0_aaaaaa_40x100.png create mode 100644 img/ui-bg_flat_75_ffffff_40x100.png create mode 100644 img/ui-bg_glass_55_fbf9ee_1x400.png create mode 100644 img/ui-bg_glass_65_ffffff_1x400.png create mode 100644 img/ui-bg_glass_75_dadada_1x400.png create mode 100644 img/ui-bg_glass_75_e6e6e6_1x400.png create mode 100644 img/ui-bg_glass_95_fef1ec_1x400.png create mode 100644 img/ui-bg_highlight-soft_75_cccccc_1x100.png create mode 100644 img/ui-icons_222222_256x240.png create mode 100644 img/ui-icons_2e83ff_256x240.png create mode 100644 img/ui-icons_454545_256x240.png create mode 100644 img/ui-icons_888888_256x240.png create mode 100644 img/ui-icons_cd0a0a_256x240.png create mode 100644 js/jquery-ui.min.js diff --git a/css/jquery-ui.css b/css/jquery-ui.css new file mode 100644 index 00000000..dbdadc2f --- /dev/null +++ b/css/jquery-ui.css @@ -0,0 +1,1225 @@ +/*! jQuery UI - v1.11.2 - 2014-12-23 +* http://jqueryui.com +* Includes: core.css, draggable.css, resizable.css, selectable.css, sortable.css, accordion.css, autocomplete.css, button.css, datepicker.css, dialog.css, menu.css, progressbar.css, selectmenu.css, slider.css, spinner.css, tabs.css, tooltip.css, theme.css +* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana%2CArial%2Csans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=highlight_soft&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=flat&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=glass&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=glass&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=glass&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=glass&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=glass&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=flat&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=flat&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px +* Copyright 2014 jQuery Foundation and other contributors; Licensed MIT */ + +/* Layout helpers +----------------------------------*/ +.ui-helper-hidden { + display: none; +} +.ui-helper-hidden-accessible { + border: 0; + clip: rect(0 0 0 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + width: 1px; +} +.ui-helper-reset { + margin: 0; + padding: 0; + border: 0; + outline: 0; + line-height: 1.3; + text-decoration: none; + font-size: 100%; + list-style: none; +} +.ui-helper-clearfix:before, +.ui-helper-clearfix:after { + content: ""; + display: table; + border-collapse: collapse; +} +.ui-helper-clearfix:after { + clear: both; +} +.ui-helper-clearfix { + min-height: 0; /* support: IE7 */ +} +.ui-helper-zfix { + width: 100%; + height: 100%; + top: 0; + left: 0; + position: absolute; + opacity: 0; + filter:Alpha(Opacity=0); /* support: IE8 */ +} + +.ui-front { + z-index: 100; +} + + +/* Interaction Cues +----------------------------------*/ +.ui-state-disabled { + cursor: default !important; +} + + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { + display: block; + text-indent: -99999px; + overflow: hidden; + background-repeat: no-repeat; +} + + +/* Misc visuals +----------------------------------*/ + +/* Overlays */ +.ui-widget-overlay { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; +} +.ui-draggable-handle { + -ms-touch-action: none; + touch-action: none; +} +.ui-resizable { + position: relative; +} +.ui-resizable-handle { + position: absolute; + font-size: 0.1px; + display: block; + -ms-touch-action: none; + touch-action: none; +} +.ui-resizable-disabled .ui-resizable-handle, +.ui-resizable-autohide .ui-resizable-handle { + display: none; +} +.ui-resizable-n { + cursor: n-resize; + height: 7px; + width: 100%; + top: -5px; + left: 0; +} +.ui-resizable-s { + cursor: s-resize; + height: 7px; + width: 100%; + bottom: -5px; + left: 0; +} +.ui-resizable-e { + cursor: e-resize; + width: 7px; + right: -5px; + top: 0; + height: 100%; +} +.ui-resizable-w { + cursor: w-resize; + width: 7px; + left: -5px; + top: 0; + height: 100%; +} +.ui-resizable-se { + cursor: se-resize; + width: 12px; + height: 12px; + right: 1px; + bottom: 1px; +} +.ui-resizable-sw { + cursor: sw-resize; + width: 9px; + height: 9px; + left: -5px; + bottom: -5px; +} +.ui-resizable-nw { + cursor: nw-resize; + width: 9px; + height: 9px; + left: -5px; + top: -5px; +} +.ui-resizable-ne { + cursor: ne-resize; + width: 9px; + height: 9px; + right: -5px; + top: -5px; +} +.ui-selectable { + -ms-touch-action: none; + touch-action: none; +} +.ui-selectable-helper { + position: absolute; + z-index: 100; + border: 1px dotted black; +} +.ui-sortable-handle { + -ms-touch-action: none; + touch-action: none; +} +.ui-accordion .ui-accordion-header { + display: block; + cursor: pointer; + position: relative; + margin: 2px 0 0 0; + padding: .5em .5em .5em .7em; + min-height: 0; /* support: IE7 */ + font-size: 100%; +} +.ui-accordion .ui-accordion-icons { + padding-left: 2.2em; +} +.ui-accordion .ui-accordion-icons .ui-accordion-icons { + padding-left: 2.2em; +} +.ui-accordion .ui-accordion-header .ui-accordion-header-icon { + position: absolute; + left: .5em; + top: 50%; + margin-top: -8px; +} +.ui-accordion .ui-accordion-content { + padding: 1em 2.2em; + border-top: 0; + overflow: auto; +} +.ui-autocomplete { + position: absolute; + top: 0; + left: 0; + cursor: default; +} +.ui-button { + display: inline-block; + position: relative; + padding: 0; + line-height: normal; + margin-right: .1em; + cursor: pointer; + vertical-align: middle; + text-align: center; + overflow: visible; /* removes extra width in IE */ +} +.ui-button, +.ui-button:link, +.ui-button:visited, +.ui-button:hover, +.ui-button:active { + text-decoration: none; +} +/* to make room for the icon, a width needs to be set here */ +.ui-button-icon-only { + width: 2.2em; +} +/* button elements seem to need a little more width */ +button.ui-button-icon-only { + width: 2.4em; +} +.ui-button-icons-only { + width: 3.4em; +} +button.ui-button-icons-only { + width: 3.7em; +} + +/* button text element */ +.ui-button .ui-button-text { + display: block; + line-height: normal; +} +.ui-button-text-only .ui-button-text { + padding: .4em 1em; +} +.ui-button-icon-only .ui-button-text, +.ui-button-icons-only .ui-button-text { + padding: .4em; + text-indent: -9999999px; +} +.ui-button-text-icon-primary .ui-button-text, +.ui-button-text-icons .ui-button-text { + padding: .4em 1em .4em 2.1em; +} +.ui-button-text-icon-secondary .ui-button-text, +.ui-button-text-icons .ui-button-text { + padding: .4em 2.1em .4em 1em; +} +.ui-button-text-icons .ui-button-text { + padding-left: 2.1em; + padding-right: 2.1em; +} +/* no icon support for input elements, provide padding by default */ +input.ui-button { + padding: .4em 1em; +} + +/* button icon element(s) */ +.ui-button-icon-only .ui-icon, +.ui-button-text-icon-primary .ui-icon, +.ui-button-text-icon-secondary .ui-icon, +.ui-button-text-icons .ui-icon, +.ui-button-icons-only .ui-icon { + position: absolute; + top: 50%; + margin-top: -8px; +} +.ui-button-icon-only .ui-icon { + left: 50%; + margin-left: -8px; +} +.ui-button-text-icon-primary .ui-button-icon-primary, +.ui-button-text-icons .ui-button-icon-primary, +.ui-button-icons-only .ui-button-icon-primary { + left: .5em; +} +.ui-button-text-icon-secondary .ui-button-icon-secondary, +.ui-button-text-icons .ui-button-icon-secondary, +.ui-button-icons-only .ui-button-icon-secondary { + right: .5em; +} + +/* button sets */ +.ui-buttonset { + margin-right: 7px; +} +.ui-buttonset .ui-button { + margin-left: 0; + margin-right: -.3em; +} + +/* workarounds */ +/* reset extra padding in Firefox, see h5bp.com/l */ +input.ui-button::-moz-focus-inner, +button.ui-button::-moz-focus-inner { + border: 0; + padding: 0; +} +.ui-datepicker { + width: 17em; + padding: .2em .2em 0; + display: none; +} +.ui-datepicker .ui-datepicker-header { + position: relative; + padding: .2em 0; +} +.ui-datepicker .ui-datepicker-prev, +.ui-datepicker .ui-datepicker-next { + position: absolute; + top: 2px; + width: 1.8em; + height: 1.8em; +} +.ui-datepicker .ui-datepicker-prev-hover, +.ui-datepicker .ui-datepicker-next-hover { + top: 1px; +} +.ui-datepicker .ui-datepicker-prev { + left: 2px; +} +.ui-datepicker .ui-datepicker-next { + right: 2px; +} +.ui-datepicker .ui-datepicker-prev-hover { + left: 1px; +} +.ui-datepicker .ui-datepicker-next-hover { + right: 1px; +} +.ui-datepicker .ui-datepicker-prev span, +.ui-datepicker .ui-datepicker-next span { + display: block; + position: absolute; + left: 50%; + margin-left: -8px; + top: 50%; + margin-top: -8px; +} +.ui-datepicker .ui-datepicker-title { + margin: 0 2.3em; + line-height: 1.8em; + text-align: center; +} +.ui-datepicker .ui-datepicker-title select { + font-size: 1em; + margin: 1px 0; +} +.ui-datepicker select.ui-datepicker-month, +.ui-datepicker select.ui-datepicker-year { + width: 45%; +} +.ui-datepicker table { + width: 100%; + font-size: .9em; + border-collapse: collapse; + margin: 0 0 .4em; +} +.ui-datepicker th { + padding: .7em .3em; + text-align: center; + font-weight: bold; + border: 0; +} +.ui-datepicker td { + border: 0; + padding: 1px; +} +.ui-datepicker td span, +.ui-datepicker td a { + display: block; + padding: .2em; + text-align: right; + text-decoration: none; +} +.ui-datepicker .ui-datepicker-buttonpane { + background-image: none; + margin: .7em 0 0 0; + padding: 0 .2em; + border-left: 0; + border-right: 0; + border-bottom: 0; +} +.ui-datepicker .ui-datepicker-buttonpane button { + float: right; + margin: .5em .2em .4em; + cursor: pointer; + padding: .2em .6em .3em .6em; + width: auto; + overflow: visible; +} +.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { + float: left; +} + +/* with multiple calendars */ +.ui-datepicker.ui-datepicker-multi { + width: auto; +} +.ui-datepicker-multi .ui-datepicker-group { + float: left; +} +.ui-datepicker-multi .ui-datepicker-group table { + width: 95%; + margin: 0 auto .4em; +} +.ui-datepicker-multi-2 .ui-datepicker-group { + width: 50%; +} +.ui-datepicker-multi-3 .ui-datepicker-group { + width: 33.3%; +} +.ui-datepicker-multi-4 .ui-datepicker-group { + width: 25%; +} +.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header, +.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { + border-left-width: 0; +} +.ui-datepicker-multi .ui-datepicker-buttonpane { + clear: left; +} +.ui-datepicker-row-break { + clear: both; + width: 100%; + font-size: 0; +} + +/* RTL support */ +.ui-datepicker-rtl { + direction: rtl; +} +.ui-datepicker-rtl .ui-datepicker-prev { + right: 2px; + left: auto; +} +.ui-datepicker-rtl .ui-datepicker-next { + left: 2px; + right: auto; +} +.ui-datepicker-rtl .ui-datepicker-prev:hover { + right: 1px; + left: auto; +} +.ui-datepicker-rtl .ui-datepicker-next:hover { + left: 1px; + right: auto; +} +.ui-datepicker-rtl .ui-datepicker-buttonpane { + clear: right; +} +.ui-datepicker-rtl .ui-datepicker-buttonpane button { + float: left; +} +.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current, +.ui-datepicker-rtl .ui-datepicker-group { + float: right; +} +.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header, +.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { + border-right-width: 0; + border-left-width: 1px; +} +.ui-dialog { + overflow: hidden; + position: absolute; + top: 0; + left: 0; + padding: .2em; + outline: 0; +} +.ui-dialog .ui-dialog-titlebar { + padding: .4em 1em; + position: relative; +} +.ui-dialog .ui-dialog-title { + float: left; + margin: .1em 0; + white-space: nowrap; + width: 90%; + overflow: hidden; + text-overflow: ellipsis; +} +.ui-dialog .ui-dialog-titlebar-close { + position: absolute; + right: .3em; + top: 50%; + width: 20px; + margin: -10px 0 0 0; + padding: 1px; + height: 20px; +} +.ui-dialog .ui-dialog-content { + position: relative; + border: 0; + padding: .5em 1em; + background: none; + overflow: auto; +} +.ui-dialog .ui-dialog-buttonpane { + text-align: left; + border-width: 1px 0 0 0; + background-image: none; + margin-top: .5em; + padding: .3em 1em .5em .4em; +} +.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { + float: right; +} +.ui-dialog .ui-dialog-buttonpane button { + margin: .5em .4em .5em 0; + cursor: pointer; +} +.ui-dialog .ui-resizable-se { + width: 12px; + height: 12px; + right: -5px; + bottom: -5px; + background-position: 16px 16px; +} +.ui-draggable .ui-dialog-titlebar { + cursor: move; +} +.ui-menu { + list-style: none; + padding: 0; + margin: 0; + display: block; + outline: none; +} +.ui-menu .ui-menu { + position: absolute; +} +.ui-menu .ui-menu-item { + position: relative; + margin: 0; + padding: 3px 1em 3px .4em; + cursor: pointer; + min-height: 0; /* support: IE7 */ + /* support: IE10, see #8844 */ + list-style-image: url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"); +} +.ui-menu .ui-menu-divider { + margin: 5px 0; + height: 0; + font-size: 0; + line-height: 0; + border-width: 1px 0 0 0; +} +.ui-menu .ui-state-focus, +.ui-menu .ui-state-active { + margin: -1px; +} + +/* icon support */ +.ui-menu-icons { + position: relative; +} +.ui-menu-icons .ui-menu-item { + padding-left: 2em; +} + +/* left-aligned */ +.ui-menu .ui-icon { + position: absolute; + top: 0; + bottom: 0; + left: .2em; + margin: auto 0; +} + +/* right-aligned */ +.ui-menu .ui-menu-icon { + left: auto; + right: 0; +} +.ui-progressbar { + height: 2em; + text-align: left; + overflow: hidden; +} +.ui-progressbar .ui-progressbar-value { + margin: -1px; + height: 100%; +} +.ui-progressbar .ui-progressbar-overlay { + background: url("data:image/gif;base64,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"); + height: 100%; + filter: alpha(opacity=25); /* support: IE8 */ + opacity: 0.25; +} +.ui-progressbar-indeterminate .ui-progressbar-value { + background-image: none; +} +.ui-selectmenu-menu { + padding: 0; + margin: 0; + position: absolute; + top: 0; + left: 0; + display: none; +} +.ui-selectmenu-menu .ui-menu { + overflow: auto; + /* Support: IE7 */ + overflow-x: hidden; + padding-bottom: 1px; +} +.ui-selectmenu-menu .ui-menu .ui-selectmenu-optgroup { + font-size: 1em; + font-weight: bold; + line-height: 1.5; + padding: 2px 0.4em; + margin: 0.5em 0 0 0; + height: auto; + border: 0; +} +.ui-selectmenu-open { + display: block; +} +.ui-selectmenu-button { + display: inline-block; + overflow: hidden; + position: relative; + text-decoration: none; + cursor: pointer; +} +.ui-selectmenu-button span.ui-icon { + right: 0.5em; + left: auto; + margin-top: -8px; + position: absolute; + top: 50%; +} +.ui-selectmenu-button span.ui-selectmenu-text { + text-align: left; + padding: 0.4em 2.1em 0.4em 1em; + display: block; + line-height: 1.4; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +.ui-slider { + position: relative; + text-align: left; +} +.ui-slider .ui-slider-handle { + position: absolute; + z-index: 2; + width: 1.2em; + height: 1.2em; + cursor: default; + -ms-touch-action: none; + touch-action: none; +} +.ui-slider .ui-slider-range { + position: absolute; + z-index: 1; + font-size: .7em; + display: block; + border: 0; + background-position: 0 0; +} + +/* support: IE8 - See #6727 */ +.ui-slider.ui-state-disabled .ui-slider-handle, +.ui-slider.ui-state-disabled .ui-slider-range { + filter: inherit; +} + +.ui-slider-horizontal { + height: .8em; +} +.ui-slider-horizontal .ui-slider-handle { + top: -.3em; + margin-left: -.6em; +} +.ui-slider-horizontal .ui-slider-range { + top: 0; + height: 100%; +} +.ui-slider-horizontal .ui-slider-range-min { + left: 0; +} +.ui-slider-horizontal .ui-slider-range-max { + right: 0; +} + +.ui-slider-vertical { + width: .8em; + height: 100px; +} +.ui-slider-vertical .ui-slider-handle { + left: -.3em; + margin-left: 0; + margin-bottom: -.6em; +} +.ui-slider-vertical .ui-slider-range { + left: 0; + width: 100%; +} +.ui-slider-vertical .ui-slider-range-min { + bottom: 0; +} +.ui-slider-vertical .ui-slider-range-max { + top: 0; +} +.ui-spinner { + position: relative; + display: inline-block; + overflow: hidden; + padding: 0; + vertical-align: middle; +} +.ui-spinner-input { + border: none; + background: none; + color: inherit; + padding: 0; + margin: .2em 0; + vertical-align: middle; + margin-left: .4em; + margin-right: 22px; +} +.ui-spinner-button { + width: 16px; + height: 50%; + font-size: .5em; + padding: 0; + margin: 0; + text-align: center; + position: absolute; + cursor: default; + display: block; + overflow: hidden; + right: 0; +} +/* more specificity required here to override default borders */ +.ui-spinner a.ui-spinner-button { + border-top: none; + border-bottom: none; + border-right: none; +} +/* vertically center icon */ +.ui-spinner .ui-icon { + position: absolute; + margin-top: -8px; + top: 50%; + left: 0; +} +.ui-spinner-up { + top: 0; +} +.ui-spinner-down { + bottom: 0; +} + +/* TR overrides */ +.ui-spinner .ui-icon-triangle-1-s { + /* need to fix icons sprite */ + background-position: -65px -16px; +} +.ui-tabs { + position: relative;/* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */ + padding: .2em; +} +.ui-tabs .ui-tabs-nav { + margin: 0; + padding: .2em .2em 0; +} +.ui-tabs .ui-tabs-nav li { + list-style: none; + float: left; + position: relative; + top: 0; + margin: 1px .2em 0 0; + border-bottom-width: 0; + padding: 0; + white-space: nowrap; +} +.ui-tabs .ui-tabs-nav .ui-tabs-anchor { + float: left; + padding: .5em 1em; + text-decoration: none; +} +.ui-tabs .ui-tabs-nav li.ui-tabs-active { + margin-bottom: -1px; + padding-bottom: 1px; +} +.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor, +.ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor, +.ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor { + cursor: text; +} +.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor { + cursor: pointer; +} +.ui-tabs .ui-tabs-panel { + display: block; + border-width: 0; + padding: 1em 1.4em; + background: none; +} +.ui-tooltip { + padding: 8px; + position: absolute; + z-index: 9999; + max-width: 300px; + -webkit-box-shadow: 0 0 5px #aaa; + box-shadow: 0 0 5px #aaa; +} +body .ui-tooltip { + border-width: 2px; +} + +/* Component containers +----------------------------------*/ +.ui-widget { + font-family: Verdana,Arial,sans-serif; + font-size: 1.1em; +} +.ui-widget .ui-widget { + font-size: 1em; +} +.ui-widget input, +.ui-widget select, +.ui-widget textarea, +.ui-widget button { + font-family: Verdana,Arial,sans-serif; + font-size: 1em; +} +.ui-widget-content { + border: 1px solid #aaaaaa; + background: #ffffff url("../img/ui-bg_flat_75_ffffff_40x100.png") 50% 50% repeat-x; + color: #222222; +} +.ui-widget-content a { + color: #222222; +} +.ui-widget-header { + border: 1px solid #aaaaaa; + background: #cccccc url("../img/ui-bg_highlight-soft_75_cccccc_1x100.png") 50% 50% repeat-x; + color: #222222; + font-weight: bold; +} +.ui-widget-header a { + color: #222222; +} + +/* Interaction states +----------------------------------*/ +.ui-state-default, +.ui-widget-content .ui-state-default, +.ui-widget-header .ui-state-default { + border: 1px solid #d3d3d3; + background: #e6e6e6 url("../img/ui-bg_glass_75_e6e6e6_1x400.png") 50% 50% repeat-x; + font-weight: normal; + color: #555555; +} +.ui-state-default a, +.ui-state-default a:link, +.ui-state-default a:visited { + color: #555555; + text-decoration: none; +} +.ui-state-hover, +.ui-widget-content .ui-state-hover, +.ui-widget-header .ui-state-hover, +.ui-state-focus, +.ui-widget-content .ui-state-focus, +.ui-widget-header .ui-state-focus { + border: 1px solid #999999; + background: #dadada url("../img/ui-bg_glass_75_dadada_1x400.png") 50% 50% repeat-x; + font-weight: normal; + color: #212121; +} +.ui-state-hover a, +.ui-state-hover a:hover, +.ui-state-hover a:link, +.ui-state-hover a:visited, +.ui-state-focus a, +.ui-state-focus a:hover, +.ui-state-focus a:link, +.ui-state-focus a:visited { + color: #212121; + text-decoration: none; +} +.ui-state-active, +.ui-widget-content .ui-state-active, +.ui-widget-header .ui-state-active { + border: 1px solid #aaaaaa; + background: #ffffff url("../img/ui-bg_glass_65_ffffff_1x400.png") 50% 50% repeat-x; + font-weight: normal; + color: #212121; +} +.ui-state-active a, +.ui-state-active a:link, +.ui-state-active a:visited { + color: #212121; + text-decoration: none; +} + +/* Interaction Cues +----------------------------------*/ +.ui-state-highlight, +.ui-widget-content .ui-state-highlight, +.ui-widget-header .ui-state-highlight { + border: 1px solid #fcefa1; + background: #fbf9ee url("../img/ui-bg_glass_55_fbf9ee_1x400.png") 50% 50% repeat-x; + color: #363636; +} +.ui-state-highlight a, +.ui-widget-content .ui-state-highlight a, +.ui-widget-header .ui-state-highlight a { + color: #363636; +} +.ui-state-error, +.ui-widget-content .ui-state-error, +.ui-widget-header .ui-state-error { + border: 1px solid #cd0a0a; + background: #fef1ec url("../img/ui-bg_glass_95_fef1ec_1x400.png") 50% 50% repeat-x; + color: #cd0a0a; +} +.ui-state-error a, +.ui-widget-content .ui-state-error a, +.ui-widget-header .ui-state-error a { + color: #cd0a0a; +} +.ui-state-error-text, +.ui-widget-content .ui-state-error-text, +.ui-widget-header .ui-state-error-text { + color: #cd0a0a; +} +.ui-priority-primary, +.ui-widget-content .ui-priority-primary, +.ui-widget-header .ui-priority-primary { + font-weight: bold; +} +.ui-priority-secondary, +.ui-widget-content .ui-priority-secondary, +.ui-widget-header .ui-priority-secondary { + opacity: .7; + filter:Alpha(Opacity=70); /* support: IE8 */ + font-weight: normal; +} +.ui-state-disabled, +.ui-widget-content .ui-state-disabled, +.ui-widget-header .ui-state-disabled { + opacity: .35; + filter:Alpha(Opacity=35); /* support: IE8 */ + background-image: none; +} +.ui-state-disabled .ui-icon { + filter:Alpha(Opacity=35); /* support: IE8 - See #6059 */ +} + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { + width: 16px; + height: 16px; +} +.ui-icon, +.ui-widget-content .ui-icon { + background-image: url("../img/ui-icons_222222_256x240.png"); +} +.ui-widget-header .ui-icon { + background-image: url("../img/ui-icons_222222_256x240.png"); +} +.ui-state-default .ui-icon { + background-image: url("../img/ui-icons_888888_256x240.png"); +} +.ui-state-hover .ui-icon, +.ui-state-focus .ui-icon { + background-image: url("../img/ui-icons_454545_256x240.png"); +} +.ui-state-active .ui-icon { + background-image: url("../img/ui-icons_454545_256x240.png"); +} +.ui-state-highlight .ui-icon { + background-image: url("../img/ui-icons_2e83ff_256x240.png"); +} +.ui-state-error .ui-icon, +.ui-state-error-text .ui-icon { + background-image: url("../img/ui-icons_cd0a0a_256x240.png"); +} + +/* positioning */ +.ui-icon-blank { background-position: 16px 16px; } +.ui-icon-carat-1-n { background-position: 0 0; } +.ui-icon-carat-1-ne { background-position: -16px 0; } +.ui-icon-carat-1-e { background-position: -32px 0; } +.ui-icon-carat-1-se { background-position: -48px 0; } +.ui-icon-carat-1-s { background-position: -64px 0; } +.ui-icon-carat-1-sw { background-position: -80px 0; } +.ui-icon-carat-1-w { background-position: -96px 0; } +.ui-icon-carat-1-nw { background-position: -112px 0; } +.ui-icon-carat-2-n-s { background-position: -128px 0; } +.ui-icon-carat-2-e-w { background-position: -144px 0; } +.ui-icon-triangle-1-n { background-position: 0 -16px; } +.ui-icon-triangle-1-ne { background-position: -16px -16px; } +.ui-icon-triangle-1-e { background-position: -32px -16px; } +.ui-icon-triangle-1-se { background-position: -48px -16px; } +.ui-icon-triangle-1-s { background-position: -64px -16px; } +.ui-icon-triangle-1-sw { background-position: -80px -16px; } +.ui-icon-triangle-1-w { background-position: -96px -16px; } +.ui-icon-triangle-1-nw { background-position: -112px -16px; } +.ui-icon-triangle-2-n-s { background-position: -128px -16px; } +.ui-icon-triangle-2-e-w { background-position: -144px -16px; } +.ui-icon-arrow-1-n { background-position: 0 -32px; } +.ui-icon-arrow-1-ne { background-position: -16px -32px; } +.ui-icon-arrow-1-e { background-position: -32px -32px; } +.ui-icon-arrow-1-se { background-position: -48px -32px; } +.ui-icon-arrow-1-s { background-position: -64px -32px; } +.ui-icon-arrow-1-sw { background-position: -80px -32px; } +.ui-icon-arrow-1-w { background-position: -96px -32px; } +.ui-icon-arrow-1-nw { background-position: -112px -32px; } +.ui-icon-arrow-2-n-s { background-position: -128px -32px; } +.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } +.ui-icon-arrow-2-e-w { background-position: -160px -32px; } +.ui-icon-arrow-2-se-nw { background-position: -176px -32px; } +.ui-icon-arrowstop-1-n { background-position: -192px -32px; } +.ui-icon-arrowstop-1-e { background-position: -208px -32px; } +.ui-icon-arrowstop-1-s { background-position: -224px -32px; } +.ui-icon-arrowstop-1-w { background-position: -240px -32px; } +.ui-icon-arrowthick-1-n { background-position: 0 -48px; } +.ui-icon-arrowthick-1-ne { background-position: -16px -48px; } +.ui-icon-arrowthick-1-e { background-position: -32px -48px; } +.ui-icon-arrowthick-1-se { background-position: -48px -48px; } +.ui-icon-arrowthick-1-s { background-position: -64px -48px; } +.ui-icon-arrowthick-1-sw { background-position: -80px -48px; } +.ui-icon-arrowthick-1-w { background-position: -96px -48px; } +.ui-icon-arrowthick-1-nw { background-position: -112px -48px; } +.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } +.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } +.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } +.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } +.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } +.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } +.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } +.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } +.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } +.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } +.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } +.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } +.ui-icon-arrowreturn-1-w { background-position: -64px -64px; } +.ui-icon-arrowreturn-1-n { background-position: -80px -64px; } +.ui-icon-arrowreturn-1-e { background-position: -96px -64px; } +.ui-icon-arrowreturn-1-s { background-position: -112px -64px; } +.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } +.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } +.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } +.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } +.ui-icon-arrow-4 { background-position: 0 -80px; } +.ui-icon-arrow-4-diag { background-position: -16px -80px; } +.ui-icon-extlink { background-position: -32px -80px; } +.ui-icon-newwin { background-position: -48px -80px; } +.ui-icon-refresh { background-position: -64px -80px; } +.ui-icon-shuffle { background-position: -80px -80px; } +.ui-icon-transfer-e-w { background-position: -96px -80px; } +.ui-icon-transferthick-e-w { background-position: -112px -80px; } +.ui-icon-folder-collapsed { background-position: 0 -96px; } +.ui-icon-folder-open { background-position: -16px -96px; } +.ui-icon-document { background-position: -32px -96px; } +.ui-icon-document-b { background-position: -48px -96px; } +.ui-icon-note { background-position: -64px -96px; } +.ui-icon-mail-closed { background-position: -80px -96px; } +.ui-icon-mail-open { background-position: -96px -96px; } +.ui-icon-suitcase { background-position: -112px -96px; } +.ui-icon-comment { background-position: -128px -96px; } +.ui-icon-person { background-position: -144px -96px; } +.ui-icon-print { background-position: -160px -96px; } +.ui-icon-trash { background-position: -176px -96px; } +.ui-icon-locked { background-position: -192px -96px; } +.ui-icon-unlocked { background-position: -208px -96px; } +.ui-icon-bookmark { background-position: -224px -96px; } +.ui-icon-tag { background-position: -240px -96px; } +.ui-icon-home { background-position: 0 -112px; } +.ui-icon-flag { background-position: -16px -112px; } +.ui-icon-calendar { background-position: -32px -112px; } +.ui-icon-cart { background-position: -48px -112px; } +.ui-icon-pencil { background-position: -64px -112px; } +.ui-icon-clock { background-position: -80px -112px; } +.ui-icon-disk { background-position: -96px -112px; } +.ui-icon-calculator { background-position: -112px -112px; } +.ui-icon-zoomin { background-position: -128px -112px; } +.ui-icon-zoomout { background-position: -144px -112px; } +.ui-icon-search { background-position: -160px -112px; } +.ui-icon-wrench { background-position: -176px -112px; } +.ui-icon-gear { background-position: -192px -112px; } +.ui-icon-heart { background-position: -208px -112px; } +.ui-icon-star { background-position: -224px -112px; } +.ui-icon-link { background-position: -240px -112px; } +.ui-icon-cancel { background-position: 0 -128px; } +.ui-icon-plus { background-position: -16px -128px; } +.ui-icon-plusthick { background-position: -32px -128px; } +.ui-icon-minus { background-position: -48px -128px; } +.ui-icon-minusthick { background-position: -64px -128px; } +.ui-icon-close { background-position: -80px -128px; } +.ui-icon-closethick { background-position: -96px -128px; } +.ui-icon-key { background-position: -112px -128px; } +.ui-icon-lightbulb { background-position: -128px -128px; } +.ui-icon-scissors { background-position: -144px -128px; } +.ui-icon-clipboard { background-position: -160px -128px; } +.ui-icon-copy { background-position: -176px -128px; } +.ui-icon-contact { background-position: -192px -128px; } +.ui-icon-image { background-position: -208px -128px; } +.ui-icon-video { background-position: -224px -128px; } +.ui-icon-script { background-position: -240px -128px; } +.ui-icon-alert { background-position: 0 -144px; } +.ui-icon-info { background-position: -16px -144px; } +.ui-icon-notice { background-position: -32px -144px; } +.ui-icon-help { background-position: -48px -144px; } +.ui-icon-check { background-position: -64px -144px; } +.ui-icon-bullet { background-position: -80px -144px; } +.ui-icon-radio-on { background-position: -96px -144px; } +.ui-icon-radio-off { background-position: -112px -144px; } +.ui-icon-pin-w { background-position: -128px -144px; } +.ui-icon-pin-s { background-position: -144px -144px; } +.ui-icon-play { background-position: 0 -160px; } +.ui-icon-pause { background-position: -16px -160px; } +.ui-icon-seek-next { background-position: -32px -160px; } +.ui-icon-seek-prev { background-position: -48px -160px; } +.ui-icon-seek-end { background-position: -64px -160px; } +.ui-icon-seek-start { background-position: -80px -160px; } +/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */ +.ui-icon-seek-first { background-position: -80px -160px; } +.ui-icon-stop { background-position: -96px -160px; } +.ui-icon-eject { background-position: -112px -160px; } +.ui-icon-volume-off { background-position: -128px -160px; } +.ui-icon-volume-on { background-position: -144px -160px; } +.ui-icon-power { background-position: 0 -176px; } +.ui-icon-signal-diag { background-position: -16px -176px; } +.ui-icon-signal { background-position: -32px -176px; } +.ui-icon-battery-0 { background-position: -48px -176px; } +.ui-icon-battery-1 { background-position: -64px -176px; } +.ui-icon-battery-2 { background-position: -80px -176px; } +.ui-icon-battery-3 { background-position: -96px -176px; } +.ui-icon-circle-plus { background-position: 0 -192px; } +.ui-icon-circle-minus { background-position: -16px -192px; } +.ui-icon-circle-close { background-position: -32px -192px; } +.ui-icon-circle-triangle-e { background-position: -48px -192px; } +.ui-icon-circle-triangle-s { background-position: -64px -192px; } +.ui-icon-circle-triangle-w { background-position: -80px -192px; } +.ui-icon-circle-triangle-n { background-position: -96px -192px; } +.ui-icon-circle-arrow-e { background-position: -112px -192px; } +.ui-icon-circle-arrow-s { background-position: -128px -192px; } +.ui-icon-circle-arrow-w { background-position: -144px -192px; } +.ui-icon-circle-arrow-n { background-position: -160px -192px; } +.ui-icon-circle-zoomin { background-position: -176px -192px; } +.ui-icon-circle-zoomout { background-position: -192px -192px; } +.ui-icon-circle-check { background-position: -208px -192px; } +.ui-icon-circlesmall-plus { background-position: 0 -208px; } +.ui-icon-circlesmall-minus { background-position: -16px -208px; } +.ui-icon-circlesmall-close { background-position: -32px -208px; } +.ui-icon-squaresmall-plus { background-position: -48px -208px; } +.ui-icon-squaresmall-minus { background-position: -64px -208px; } +.ui-icon-squaresmall-close { background-position: -80px -208px; } +.ui-icon-grip-dotted-vertical { background-position: 0 -224px; } +.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } +.ui-icon-grip-solid-vertical { background-position: -32px -224px; } +.ui-icon-grip-solid-horizontal { background-position: -48px -224px; } +.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } +.ui-icon-grip-diagonal-se { background-position: -80px -224px; } + + +/* Misc visuals +----------------------------------*/ + +/* Corner radius */ +.ui-corner-all, +.ui-corner-top, +.ui-corner-left, +.ui-corner-tl { + border-top-left-radius: 4px; +} +.ui-corner-all, +.ui-corner-top, +.ui-corner-right, +.ui-corner-tr { + border-top-right-radius: 4px; +} +.ui-corner-all, +.ui-corner-bottom, +.ui-corner-left, +.ui-corner-bl { + border-bottom-left-radius: 4px; +} +.ui-corner-all, +.ui-corner-bottom, +.ui-corner-right, +.ui-corner-br { + border-bottom-right-radius: 4px; +} + +/* Overlays */ +.ui-widget-overlay { + background: #aaaaaa url("../img/ui-bg_flat_0_aaaaaa_40x100.png") 50% 50% repeat-x; + opacity: .3; + filter: Alpha(Opacity=30); /* support: IE8 */ +} +.ui-widget-shadow { + margin: -8px 0 0 -8px; + padding: 8px; + background: #aaaaaa url("../img/ui-bg_flat_0_aaaaaa_40x100.png") 50% 50% repeat-x; + opacity: .3; + filter: Alpha(Opacity=30); /* support: IE8 */ + border-radius: 8px; +} diff --git a/css/jquery-ui.structure.css b/css/jquery-ui.structure.css new file mode 100644 index 00000000..d3d88d44 --- /dev/null +++ b/css/jquery-ui.structure.css @@ -0,0 +1,833 @@ +/*! + * jQuery UI CSS Framework 1.11.2 + * http://jqueryui.com + * + * Copyright 2014 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://api.jqueryui.com/category/theming/ + */ + +/* Layout helpers +----------------------------------*/ +.ui-helper-hidden { + display: none; +} +.ui-helper-hidden-accessible { + border: 0; + clip: rect(0 0 0 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + width: 1px; +} +.ui-helper-reset { + margin: 0; + padding: 0; + border: 0; + outline: 0; + line-height: 1.3; + text-decoration: none; + font-size: 100%; + list-style: none; +} +.ui-helper-clearfix:before, +.ui-helper-clearfix:after { + content: ""; + display: table; + border-collapse: collapse; +} +.ui-helper-clearfix:after { + clear: both; +} +.ui-helper-clearfix { + min-height: 0; /* support: IE7 */ +} +.ui-helper-zfix { + width: 100%; + height: 100%; + top: 0; + left: 0; + position: absolute; + opacity: 0; + filter:Alpha(Opacity=0); /* support: IE8 */ +} + +.ui-front { + z-index: 100; +} + + +/* Interaction Cues +----------------------------------*/ +.ui-state-disabled { + cursor: default !important; +} + + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { + display: block; + text-indent: -99999px; + overflow: hidden; + background-repeat: no-repeat; +} + + +/* Misc visuals +----------------------------------*/ + +/* Overlays */ +.ui-widget-overlay { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; +} +.ui-draggable-handle { + -ms-touch-action: none; + touch-action: none; +} +.ui-resizable { + position: relative; +} +.ui-resizable-handle { + position: absolute; + font-size: 0.1px; + display: block; + -ms-touch-action: none; + touch-action: none; +} +.ui-resizable-disabled .ui-resizable-handle, +.ui-resizable-autohide .ui-resizable-handle { + display: none; +} +.ui-resizable-n { + cursor: n-resize; + height: 7px; + width: 100%; + top: -5px; + left: 0; +} +.ui-resizable-s { + cursor: s-resize; + height: 7px; + width: 100%; + bottom: -5px; + left: 0; +} +.ui-resizable-e { + cursor: e-resize; + width: 7px; + right: -5px; + top: 0; + height: 100%; +} +.ui-resizable-w { + cursor: w-resize; + width: 7px; + left: -5px; + top: 0; + height: 100%; +} +.ui-resizable-se { + cursor: se-resize; + width: 12px; + height: 12px; + right: 1px; + bottom: 1px; +} +.ui-resizable-sw { + cursor: sw-resize; + width: 9px; + height: 9px; + left: -5px; + bottom: -5px; +} +.ui-resizable-nw { + cursor: nw-resize; + width: 9px; + height: 9px; + left: -5px; + top: -5px; +} +.ui-resizable-ne { + cursor: ne-resize; + width: 9px; + height: 9px; + right: -5px; + top: -5px; +} +.ui-selectable { + -ms-touch-action: none; + touch-action: none; +} +.ui-selectable-helper { + position: absolute; + z-index: 100; + border: 1px dotted black; +} +.ui-sortable-handle { + -ms-touch-action: none; + touch-action: none; +} +.ui-accordion .ui-accordion-header { + display: block; + cursor: pointer; + position: relative; + margin: 2px 0 0 0; + padding: .5em .5em .5em .7em; + min-height: 0; /* support: IE7 */ + font-size: 100%; +} +.ui-accordion .ui-accordion-icons { + padding-left: 2.2em; +} +.ui-accordion .ui-accordion-icons .ui-accordion-icons { + padding-left: 2.2em; +} +.ui-accordion .ui-accordion-header .ui-accordion-header-icon { + position: absolute; + left: .5em; + top: 50%; + margin-top: -8px; +} +.ui-accordion .ui-accordion-content { + padding: 1em 2.2em; + border-top: 0; + overflow: auto; +} +.ui-autocomplete { + position: absolute; + top: 0; + left: 0; + cursor: default; +} +.ui-button { + display: inline-block; + position: relative; + padding: 0; + line-height: normal; + margin-right: .1em; + cursor: pointer; + vertical-align: middle; + text-align: center; + overflow: visible; /* removes extra width in IE */ +} +.ui-button, +.ui-button:link, +.ui-button:visited, +.ui-button:hover, +.ui-button:active { + text-decoration: none; +} +/* to make room for the icon, a width needs to be set here */ +.ui-button-icon-only { + width: 2.2em; +} +/* button elements seem to need a little more width */ +button.ui-button-icon-only { + width: 2.4em; +} +.ui-button-icons-only { + width: 3.4em; +} +button.ui-button-icons-only { + width: 3.7em; +} + +/* button text element */ +.ui-button .ui-button-text { + display: block; + line-height: normal; +} +.ui-button-text-only .ui-button-text { + padding: .4em 1em; +} +.ui-button-icon-only .ui-button-text, +.ui-button-icons-only .ui-button-text { + padding: .4em; + text-indent: -9999999px; +} +.ui-button-text-icon-primary .ui-button-text, +.ui-button-text-icons .ui-button-text { + padding: .4em 1em .4em 2.1em; +} +.ui-button-text-icon-secondary .ui-button-text, +.ui-button-text-icons .ui-button-text { + padding: .4em 2.1em .4em 1em; +} +.ui-button-text-icons .ui-button-text { + padding-left: 2.1em; + padding-right: 2.1em; +} +/* no icon support for input elements, provide padding by default */ +input.ui-button { + padding: .4em 1em; +} + +/* button icon element(s) */ +.ui-button-icon-only .ui-icon, +.ui-button-text-icon-primary .ui-icon, +.ui-button-text-icon-secondary .ui-icon, +.ui-button-text-icons .ui-icon, +.ui-button-icons-only .ui-icon { + position: absolute; + top: 50%; + margin-top: -8px; +} +.ui-button-icon-only .ui-icon { + left: 50%; + margin-left: -8px; +} +.ui-button-text-icon-primary .ui-button-icon-primary, +.ui-button-text-icons .ui-button-icon-primary, +.ui-button-icons-only .ui-button-icon-primary { + left: .5em; +} +.ui-button-text-icon-secondary .ui-button-icon-secondary, +.ui-button-text-icons .ui-button-icon-secondary, +.ui-button-icons-only .ui-button-icon-secondary { + right: .5em; +} + +/* button sets */ +.ui-buttonset { + margin-right: 7px; +} +.ui-buttonset .ui-button { + margin-left: 0; + margin-right: -.3em; +} + +/* workarounds */ +/* reset extra padding in Firefox, see h5bp.com/l */ +input.ui-button::-moz-focus-inner, +button.ui-button::-moz-focus-inner { + border: 0; + padding: 0; +} +.ui-datepicker { + width: 17em; + padding: .2em .2em 0; + display: none; +} +.ui-datepicker .ui-datepicker-header { + position: relative; + padding: .2em 0; +} +.ui-datepicker .ui-datepicker-prev, +.ui-datepicker .ui-datepicker-next { + position: absolute; + top: 2px; + width: 1.8em; + height: 1.8em; +} +.ui-datepicker .ui-datepicker-prev-hover, +.ui-datepicker .ui-datepicker-next-hover { + top: 1px; +} +.ui-datepicker .ui-datepicker-prev { + left: 2px; +} +.ui-datepicker .ui-datepicker-next { + right: 2px; +} +.ui-datepicker .ui-datepicker-prev-hover { + left: 1px; +} +.ui-datepicker .ui-datepicker-next-hover { + right: 1px; +} +.ui-datepicker .ui-datepicker-prev span, +.ui-datepicker .ui-datepicker-next span { + display: block; + position: absolute; + left: 50%; + margin-left: -8px; + top: 50%; + margin-top: -8px; +} +.ui-datepicker .ui-datepicker-title { + margin: 0 2.3em; + line-height: 1.8em; + text-align: center; +} +.ui-datepicker .ui-datepicker-title select { + font-size: 1em; + margin: 1px 0; +} +.ui-datepicker select.ui-datepicker-month, +.ui-datepicker select.ui-datepicker-year { + width: 45%; +} +.ui-datepicker table { + width: 100%; + font-size: .9em; + border-collapse: collapse; + margin: 0 0 .4em; +} +.ui-datepicker th { + padding: .7em .3em; + text-align: center; + font-weight: bold; + border: 0; +} +.ui-datepicker td { + border: 0; + padding: 1px; +} +.ui-datepicker td span, +.ui-datepicker td a { + display: block; + padding: .2em; + text-align: right; + text-decoration: none; +} +.ui-datepicker .ui-datepicker-buttonpane { + background-image: none; + margin: .7em 0 0 0; + padding: 0 .2em; + border-left: 0; + border-right: 0; + border-bottom: 0; +} +.ui-datepicker .ui-datepicker-buttonpane button { + float: right; + margin: .5em .2em .4em; + cursor: pointer; + padding: .2em .6em .3em .6em; + width: auto; + overflow: visible; +} +.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { + float: left; +} + +/* with multiple calendars */ +.ui-datepicker.ui-datepicker-multi { + width: auto; +} +.ui-datepicker-multi .ui-datepicker-group { + float: left; +} +.ui-datepicker-multi .ui-datepicker-group table { + width: 95%; + margin: 0 auto .4em; +} +.ui-datepicker-multi-2 .ui-datepicker-group { + width: 50%; +} +.ui-datepicker-multi-3 .ui-datepicker-group { + width: 33.3%; +} +.ui-datepicker-multi-4 .ui-datepicker-group { + width: 25%; +} +.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header, +.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { + border-left-width: 0; +} +.ui-datepicker-multi .ui-datepicker-buttonpane { + clear: left; +} +.ui-datepicker-row-break { + clear: both; + width: 100%; + font-size: 0; +} + +/* RTL support */ +.ui-datepicker-rtl { + direction: rtl; +} +.ui-datepicker-rtl .ui-datepicker-prev { + right: 2px; + left: auto; +} +.ui-datepicker-rtl .ui-datepicker-next { + left: 2px; + right: auto; +} +.ui-datepicker-rtl .ui-datepicker-prev:hover { + right: 1px; + left: auto; +} +.ui-datepicker-rtl .ui-datepicker-next:hover { + left: 1px; + right: auto; +} +.ui-datepicker-rtl .ui-datepicker-buttonpane { + clear: right; +} +.ui-datepicker-rtl .ui-datepicker-buttonpane button { + float: left; +} +.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current, +.ui-datepicker-rtl .ui-datepicker-group { + float: right; +} +.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header, +.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { + border-right-width: 0; + border-left-width: 1px; +} +.ui-dialog { + overflow: hidden; + position: absolute; + top: 0; + left: 0; + padding: .2em; + outline: 0; +} +.ui-dialog .ui-dialog-titlebar { + padding: .4em 1em; + position: relative; +} +.ui-dialog .ui-dialog-title { + float: left; + margin: .1em 0; + white-space: nowrap; + width: 90%; + overflow: hidden; + text-overflow: ellipsis; +} +.ui-dialog .ui-dialog-titlebar-close { + position: absolute; + right: .3em; + top: 50%; + width: 20px; + margin: -10px 0 0 0; + padding: 1px; + height: 20px; +} +.ui-dialog .ui-dialog-content { + position: relative; + border: 0; + padding: .5em 1em; + background: none; + overflow: auto; +} +.ui-dialog .ui-dialog-buttonpane { + text-align: left; + border-width: 1px 0 0 0; + background-image: none; + margin-top: .5em; + padding: .3em 1em .5em .4em; +} +.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { + float: right; +} +.ui-dialog .ui-dialog-buttonpane button { + margin: .5em .4em .5em 0; + cursor: pointer; +} +.ui-dialog .ui-resizable-se { + width: 12px; + height: 12px; + right: -5px; + bottom: -5px; + background-position: 16px 16px; +} +.ui-draggable .ui-dialog-titlebar { + cursor: move; +} +.ui-menu { + list-style: none; + padding: 0; + margin: 0; + display: block; + outline: none; +} +.ui-menu .ui-menu { + position: absolute; +} +.ui-menu .ui-menu-item { + position: relative; + margin: 0; + padding: 3px 1em 3px .4em; + cursor: pointer; + min-height: 0; /* support: IE7 */ + /* support: IE10, see #8844 */ + list-style-image: url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"); +} +.ui-menu .ui-menu-divider { + margin: 5px 0; + height: 0; + font-size: 0; + line-height: 0; + border-width: 1px 0 0 0; +} +.ui-menu .ui-state-focus, +.ui-menu .ui-state-active { + margin: -1px; +} + +/* icon support */ +.ui-menu-icons { + position: relative; +} +.ui-menu-icons .ui-menu-item { + padding-left: 2em; +} + +/* left-aligned */ +.ui-menu .ui-icon { + position: absolute; + top: 0; + bottom: 0; + left: .2em; + margin: auto 0; +} + +/* right-aligned */ +.ui-menu .ui-menu-icon { + left: auto; + right: 0; +} +.ui-progressbar { + height: 2em; + text-align: left; + overflow: hidden; +} +.ui-progressbar .ui-progressbar-value { + margin: -1px; + height: 100%; +} +.ui-progressbar .ui-progressbar-overlay { + background: url("data:image/gif;base64,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"); + height: 100%; + filter: alpha(opacity=25); /* support: IE8 */ + opacity: 0.25; +} +.ui-progressbar-indeterminate .ui-progressbar-value { + background-image: none; +} +.ui-selectmenu-menu { + padding: 0; + margin: 0; + position: absolute; + top: 0; + left: 0; + display: none; +} +.ui-selectmenu-menu .ui-menu { + overflow: auto; + /* Support: IE7 */ + overflow-x: hidden; + padding-bottom: 1px; +} +.ui-selectmenu-menu .ui-menu .ui-selectmenu-optgroup { + font-size: 1em; + font-weight: bold; + line-height: 1.5; + padding: 2px 0.4em; + margin: 0.5em 0 0 0; + height: auto; + border: 0; +} +.ui-selectmenu-open { + display: block; +} +.ui-selectmenu-button { + display: inline-block; + overflow: hidden; + position: relative; + text-decoration: none; + cursor: pointer; +} +.ui-selectmenu-button span.ui-icon { + right: 0.5em; + left: auto; + margin-top: -8px; + position: absolute; + top: 50%; +} +.ui-selectmenu-button span.ui-selectmenu-text { + text-align: left; + padding: 0.4em 2.1em 0.4em 1em; + display: block; + line-height: 1.4; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +.ui-slider { + position: relative; + text-align: left; +} +.ui-slider .ui-slider-handle { + position: absolute; + z-index: 2; + width: 1.2em; + height: 1.2em; + cursor: default; + -ms-touch-action: none; + touch-action: none; +} +.ui-slider .ui-slider-range { + position: absolute; + z-index: 1; + font-size: .7em; + display: block; + border: 0; + background-position: 0 0; +} + +/* support: IE8 - See #6727 */ +.ui-slider.ui-state-disabled .ui-slider-handle, +.ui-slider.ui-state-disabled .ui-slider-range { + filter: inherit; +} + +.ui-slider-horizontal { + height: .8em; +} +.ui-slider-horizontal .ui-slider-handle { + top: -.3em; + margin-left: -.6em; +} +.ui-slider-horizontal .ui-slider-range { + top: 0; + height: 100%; +} +.ui-slider-horizontal .ui-slider-range-min { + left: 0; +} +.ui-slider-horizontal .ui-slider-range-max { + right: 0; +} + +.ui-slider-vertical { + width: .8em; + height: 100px; +} +.ui-slider-vertical .ui-slider-handle { + left: -.3em; + margin-left: 0; + margin-bottom: -.6em; +} +.ui-slider-vertical .ui-slider-range { + left: 0; + width: 100%; +} +.ui-slider-vertical .ui-slider-range-min { + bottom: 0; +} +.ui-slider-vertical .ui-slider-range-max { + top: 0; +} +.ui-spinner { + position: relative; + display: inline-block; + overflow: hidden; + padding: 0; + vertical-align: middle; +} +.ui-spinner-input { + border: none; + background: none; + color: inherit; + padding: 0; + margin: .2em 0; + vertical-align: middle; + margin-left: .4em; + margin-right: 22px; +} +.ui-spinner-button { + width: 16px; + height: 50%; + font-size: .5em; + padding: 0; + margin: 0; + text-align: center; + position: absolute; + cursor: default; + display: block; + overflow: hidden; + right: 0; +} +/* more specificity required here to override default borders */ +.ui-spinner a.ui-spinner-button { + border-top: none; + border-bottom: none; + border-right: none; +} +/* vertically center icon */ +.ui-spinner .ui-icon { + position: absolute; + margin-top: -8px; + top: 50%; + left: 0; +} +.ui-spinner-up { + top: 0; +} +.ui-spinner-down { + bottom: 0; +} + +/* TR overrides */ +.ui-spinner .ui-icon-triangle-1-s { + /* need to fix icons sprite */ + background-position: -65px -16px; +} +.ui-tabs { + position: relative;/* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */ + padding: .2em; +} +.ui-tabs .ui-tabs-nav { + margin: 0; + padding: .2em .2em 0; +} +.ui-tabs .ui-tabs-nav li { + list-style: none; + float: left; + position: relative; + top: 0; + margin: 1px .2em 0 0; + border-bottom-width: 0; + padding: 0; + white-space: nowrap; +} +.ui-tabs .ui-tabs-nav .ui-tabs-anchor { + float: left; + padding: .5em 1em; + text-decoration: none; +} +.ui-tabs .ui-tabs-nav li.ui-tabs-active { + margin-bottom: -1px; + padding-bottom: 1px; +} +.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor, +.ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor, +.ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor { + cursor: text; +} +.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor { + cursor: pointer; +} +.ui-tabs .ui-tabs-panel { + display: block; + border-width: 0; + padding: 1em 1.4em; + background: none; +} +.ui-tooltip { + padding: 8px; + position: absolute; + z-index: 9999; + max-width: 300px; + -webkit-box-shadow: 0 0 5px #aaa; + box-shadow: 0 0 5px #aaa; +} +body .ui-tooltip { + border-width: 2px; +} diff --git a/css/jquery-ui.theme.css b/css/jquery-ui.theme.css new file mode 100644 index 00000000..753cc983 --- /dev/null +++ b/css/jquery-ui.theme.css @@ -0,0 +1,410 @@ +/*! + * jQuery UI CSS Framework 1.11.2 + * http://jqueryui.com + * + * Copyright 2014 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://api.jqueryui.com/category/theming/ + * + * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana%2CArial%2Csans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=highlight_soft&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=flat&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=glass&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=glass&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=glass&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=glass&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=glass&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=flat&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=flat&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px + */ + + +/* Component containers +----------------------------------*/ +.ui-widget { + font-family: Verdana,Arial,sans-serif; + font-size: 1.1em; +} +.ui-widget .ui-widget { + font-size: 1em; +} +.ui-widget input, +.ui-widget select, +.ui-widget textarea, +.ui-widget button { + font-family: Verdana,Arial,sans-serif; + font-size: 1em; +} +.ui-widget-content { + border: 1px solid #aaaaaa; + background: #ffffff url("../img/ui-bg_flat_75_ffffff_40x100.png") 50% 50% repeat-x; + color: #222222; +} +.ui-widget-content a { + color: #222222; +} +.ui-widget-header { + border: 1px solid #aaaaaa; + background: #cccccc url("../img/ui-bg_highlight-soft_75_cccccc_1x100.png") 50% 50% repeat-x; + color: #222222; + font-weight: bold; +} +.ui-widget-header a { + color: #222222; +} + +/* Interaction states +----------------------------------*/ +.ui-state-default, +.ui-widget-content .ui-state-default, +.ui-widget-header .ui-state-default { + border: 1px solid #d3d3d3; + background: #e6e6e6 url("../img/ui-bg_glass_75_e6e6e6_1x400.png") 50% 50% repeat-x; + font-weight: normal; + color: #555555; +} +.ui-state-default a, +.ui-state-default a:link, +.ui-state-default a:visited { + color: #555555; + text-decoration: none; +} +.ui-state-hover, +.ui-widget-content .ui-state-hover, +.ui-widget-header .ui-state-hover, +.ui-state-focus, +.ui-widget-content .ui-state-focus, +.ui-widget-header .ui-state-focus { + border: 1px solid #999999; + background: #dadada url("../img/ui-bg_glass_75_dadada_1x400.png") 50% 50% repeat-x; + font-weight: normal; + color: #212121; +} +.ui-state-hover a, +.ui-state-hover a:hover, +.ui-state-hover a:link, +.ui-state-hover a:visited, +.ui-state-focus a, +.ui-state-focus a:hover, +.ui-state-focus a:link, +.ui-state-focus a:visited { + color: #212121; + text-decoration: none; +} +.ui-state-active, +.ui-widget-content .ui-state-active, +.ui-widget-header .ui-state-active { + border: 1px solid #aaaaaa; + background: #ffffff url("../img/ui-bg_glass_65_ffffff_1x400.png") 50% 50% repeat-x; + font-weight: normal; + color: #212121; +} +.ui-state-active a, +.ui-state-active a:link, +.ui-state-active a:visited { + color: #212121; + text-decoration: none; +} + +/* Interaction Cues +----------------------------------*/ +.ui-state-highlight, +.ui-widget-content .ui-state-highlight, +.ui-widget-header .ui-state-highlight { + border: 1px solid #fcefa1; + background: #fbf9ee url("../img/ui-bg_glass_55_fbf9ee_1x400.png") 50% 50% repeat-x; + color: #363636; +} +.ui-state-highlight a, +.ui-widget-content .ui-state-highlight a, +.ui-widget-header .ui-state-highlight a { + color: #363636; +} +.ui-state-error, +.ui-widget-content .ui-state-error, +.ui-widget-header .ui-state-error { + border: 1px solid #cd0a0a; + background: #fef1ec url("../img/ui-bg_glass_95_fef1ec_1x400.png") 50% 50% repeat-x; + color: #cd0a0a; +} +.ui-state-error a, +.ui-widget-content .ui-state-error a, +.ui-widget-header .ui-state-error a { + color: #cd0a0a; +} +.ui-state-error-text, +.ui-widget-content .ui-state-error-text, +.ui-widget-header .ui-state-error-text { + color: #cd0a0a; +} +.ui-priority-primary, +.ui-widget-content .ui-priority-primary, +.ui-widget-header .ui-priority-primary { + font-weight: bold; +} +.ui-priority-secondary, +.ui-widget-content .ui-priority-secondary, +.ui-widget-header .ui-priority-secondary { + opacity: .7; + filter:Alpha(Opacity=70); /* support: IE8 */ + font-weight: normal; +} +.ui-state-disabled, +.ui-widget-content .ui-state-disabled, +.ui-widget-header .ui-state-disabled { + opacity: .35; + filter:Alpha(Opacity=35); /* support: IE8 */ + background-image: none; +} +.ui-state-disabled .ui-icon { + filter:Alpha(Opacity=35); /* support: IE8 - See #6059 */ +} + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { + width: 16px; + height: 16px; +} +.ui-icon, +.ui-widget-content .ui-icon { + background-image: url("../img/ui-icons_222222_256x240.png"); +} +.ui-widget-header .ui-icon { + background-image: url("../img/ui-icons_222222_256x240.png"); +} +.ui-state-default .ui-icon { + background-image: url("../img/ui-icons_888888_256x240.png"); +} +.ui-state-hover .ui-icon, +.ui-state-focus .ui-icon { + background-image: url("../img/ui-icons_454545_256x240.png"); +} +.ui-state-active .ui-icon { + background-image: url("../img/ui-icons_454545_256x240.png"); +} +.ui-state-highlight .ui-icon { + background-image: url("../img/ui-icons_2e83ff_256x240.png"); +} +.ui-state-error .ui-icon, +.ui-state-error-text .ui-icon { + background-image: url("../img/ui-icons_cd0a0a_256x240.png"); +} + +/* positioning */ +.ui-icon-blank { background-position: 16px 16px; } +.ui-icon-carat-1-n { background-position: 0 0; } +.ui-icon-carat-1-ne { background-position: -16px 0; } +.ui-icon-carat-1-e { background-position: -32px 0; } +.ui-icon-carat-1-se { background-position: -48px 0; } +.ui-icon-carat-1-s { background-position: -64px 0; } +.ui-icon-carat-1-sw { background-position: -80px 0; } +.ui-icon-carat-1-w { background-position: -96px 0; } +.ui-icon-carat-1-nw { background-position: -112px 0; } +.ui-icon-carat-2-n-s { background-position: -128px 0; } +.ui-icon-carat-2-e-w { background-position: -144px 0; } +.ui-icon-triangle-1-n { background-position: 0 -16px; } +.ui-icon-triangle-1-ne { background-position: -16px -16px; } +.ui-icon-triangle-1-e { background-position: -32px -16px; } +.ui-icon-triangle-1-se { background-position: -48px -16px; } +.ui-icon-triangle-1-s { background-position: -64px -16px; } +.ui-icon-triangle-1-sw { background-position: -80px -16px; } +.ui-icon-triangle-1-w { background-position: -96px -16px; } +.ui-icon-triangle-1-nw { background-position: -112px -16px; } +.ui-icon-triangle-2-n-s { background-position: -128px -16px; } +.ui-icon-triangle-2-e-w { background-position: -144px -16px; } +.ui-icon-arrow-1-n { background-position: 0 -32px; } +.ui-icon-arrow-1-ne { background-position: -16px -32px; } +.ui-icon-arrow-1-e { background-position: -32px -32px; } +.ui-icon-arrow-1-se { background-position: -48px -32px; } +.ui-icon-arrow-1-s { background-position: -64px -32px; } +.ui-icon-arrow-1-sw { background-position: -80px -32px; } +.ui-icon-arrow-1-w { background-position: -96px -32px; } +.ui-icon-arrow-1-nw { background-position: -112px -32px; } +.ui-icon-arrow-2-n-s { background-position: -128px -32px; } +.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } +.ui-icon-arrow-2-e-w { background-position: -160px -32px; } +.ui-icon-arrow-2-se-nw { background-position: -176px -32px; } +.ui-icon-arrowstop-1-n { background-position: -192px -32px; } +.ui-icon-arrowstop-1-e { background-position: -208px -32px; } +.ui-icon-arrowstop-1-s { background-position: -224px -32px; } +.ui-icon-arrowstop-1-w { background-position: -240px -32px; } +.ui-icon-arrowthick-1-n { background-position: 0 -48px; } +.ui-icon-arrowthick-1-ne { background-position: -16px -48px; } +.ui-icon-arrowthick-1-e { background-position: -32px -48px; } +.ui-icon-arrowthick-1-se { background-position: -48px -48px; } +.ui-icon-arrowthick-1-s { background-position: -64px -48px; } +.ui-icon-arrowthick-1-sw { background-position: -80px -48px; } +.ui-icon-arrowthick-1-w { background-position: -96px -48px; } +.ui-icon-arrowthick-1-nw { background-position: -112px -48px; } +.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } +.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } +.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } +.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } +.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } +.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } +.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } +.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } +.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } +.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } +.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } +.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } +.ui-icon-arrowreturn-1-w { background-position: -64px -64px; } +.ui-icon-arrowreturn-1-n { background-position: -80px -64px; } +.ui-icon-arrowreturn-1-e { background-position: -96px -64px; } +.ui-icon-arrowreturn-1-s { background-position: -112px -64px; } +.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } +.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } +.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } +.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } +.ui-icon-arrow-4 { background-position: 0 -80px; } +.ui-icon-arrow-4-diag { background-position: -16px -80px; } +.ui-icon-extlink { background-position: -32px -80px; } +.ui-icon-newwin { background-position: -48px -80px; } +.ui-icon-refresh { background-position: -64px -80px; } +.ui-icon-shuffle { background-position: -80px -80px; } +.ui-icon-transfer-e-w { background-position: -96px -80px; } +.ui-icon-transferthick-e-w { background-position: -112px -80px; } +.ui-icon-folder-collapsed { background-position: 0 -96px; } +.ui-icon-folder-open { background-position: -16px -96px; } +.ui-icon-document { background-position: -32px -96px; } +.ui-icon-document-b { background-position: -48px -96px; } +.ui-icon-note { background-position: -64px -96px; } +.ui-icon-mail-closed { background-position: -80px -96px; } +.ui-icon-mail-open { background-position: -96px -96px; } +.ui-icon-suitcase { background-position: -112px -96px; } +.ui-icon-comment { background-position: -128px -96px; } +.ui-icon-person { background-position: -144px -96px; } +.ui-icon-print { background-position: -160px -96px; } +.ui-icon-trash { background-position: -176px -96px; } +.ui-icon-locked { background-position: -192px -96px; } +.ui-icon-unlocked { background-position: -208px -96px; } +.ui-icon-bookmark { background-position: -224px -96px; } +.ui-icon-tag { background-position: -240px -96px; } +.ui-icon-home { background-position: 0 -112px; } +.ui-icon-flag { background-position: -16px -112px; } +.ui-icon-calendar { background-position: -32px -112px; } +.ui-icon-cart { background-position: -48px -112px; } +.ui-icon-pencil { background-position: -64px -112px; } +.ui-icon-clock { background-position: -80px -112px; } +.ui-icon-disk { background-position: -96px -112px; } +.ui-icon-calculator { background-position: -112px -112px; } +.ui-icon-zoomin { background-position: -128px -112px; } +.ui-icon-zoomout { background-position: -144px -112px; } +.ui-icon-search { background-position: -160px -112px; } +.ui-icon-wrench { background-position: -176px -112px; } +.ui-icon-gear { background-position: -192px -112px; } +.ui-icon-heart { background-position: -208px -112px; } +.ui-icon-star { background-position: -224px -112px; } +.ui-icon-link { background-position: -240px -112px; } +.ui-icon-cancel { background-position: 0 -128px; } +.ui-icon-plus { background-position: -16px -128px; } +.ui-icon-plusthick { background-position: -32px -128px; } +.ui-icon-minus { background-position: -48px -128px; } +.ui-icon-minusthick { background-position: -64px -128px; } +.ui-icon-close { background-position: -80px -128px; } +.ui-icon-closethick { background-position: -96px -128px; } +.ui-icon-key { background-position: -112px -128px; } +.ui-icon-lightbulb { background-position: -128px -128px; } +.ui-icon-scissors { background-position: -144px -128px; } +.ui-icon-clipboard { background-position: -160px -128px; } +.ui-icon-copy { background-position: -176px -128px; } +.ui-icon-contact { background-position: -192px -128px; } +.ui-icon-image { background-position: -208px -128px; } +.ui-icon-video { background-position: -224px -128px; } +.ui-icon-script { background-position: -240px -128px; } +.ui-icon-alert { background-position: 0 -144px; } +.ui-icon-info { background-position: -16px -144px; } +.ui-icon-notice { background-position: -32px -144px; } +.ui-icon-help { background-position: -48px -144px; } +.ui-icon-check { background-position: -64px -144px; } +.ui-icon-bullet { background-position: -80px -144px; } +.ui-icon-radio-on { background-position: -96px -144px; } +.ui-icon-radio-off { background-position: -112px -144px; } +.ui-icon-pin-w { background-position: -128px -144px; } +.ui-icon-pin-s { background-position: -144px -144px; } +.ui-icon-play { background-position: 0 -160px; } +.ui-icon-pause { background-position: -16px -160px; } +.ui-icon-seek-next { background-position: -32px -160px; } +.ui-icon-seek-prev { background-position: -48px -160px; } +.ui-icon-seek-end { background-position: -64px -160px; } +.ui-icon-seek-start { background-position: -80px -160px; } +/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */ +.ui-icon-seek-first { background-position: -80px -160px; } +.ui-icon-stop { background-position: -96px -160px; } +.ui-icon-eject { background-position: -112px -160px; } +.ui-icon-volume-off { background-position: -128px -160px; } +.ui-icon-volume-on { background-position: -144px -160px; } +.ui-icon-power { background-position: 0 -176px; } +.ui-icon-signal-diag { background-position: -16px -176px; } +.ui-icon-signal { background-position: -32px -176px; } +.ui-icon-battery-0 { background-position: -48px -176px; } +.ui-icon-battery-1 { background-position: -64px -176px; } +.ui-icon-battery-2 { background-position: -80px -176px; } +.ui-icon-battery-3 { background-position: -96px -176px; } +.ui-icon-circle-plus { background-position: 0 -192px; } +.ui-icon-circle-minus { background-position: -16px -192px; } +.ui-icon-circle-close { background-position: -32px -192px; } +.ui-icon-circle-triangle-e { background-position: -48px -192px; } +.ui-icon-circle-triangle-s { background-position: -64px -192px; } +.ui-icon-circle-triangle-w { background-position: -80px -192px; } +.ui-icon-circle-triangle-n { background-position: -96px -192px; } +.ui-icon-circle-arrow-e { background-position: -112px -192px; } +.ui-icon-circle-arrow-s { background-position: -128px -192px; } +.ui-icon-circle-arrow-w { background-position: -144px -192px; } +.ui-icon-circle-arrow-n { background-position: -160px -192px; } +.ui-icon-circle-zoomin { background-position: -176px -192px; } +.ui-icon-circle-zoomout { background-position: -192px -192px; } +.ui-icon-circle-check { background-position: -208px -192px; } +.ui-icon-circlesmall-plus { background-position: 0 -208px; } +.ui-icon-circlesmall-minus { background-position: -16px -208px; } +.ui-icon-circlesmall-close { background-position: -32px -208px; } +.ui-icon-squaresmall-plus { background-position: -48px -208px; } +.ui-icon-squaresmall-minus { background-position: -64px -208px; } +.ui-icon-squaresmall-close { background-position: -80px -208px; } +.ui-icon-grip-dotted-vertical { background-position: 0 -224px; } +.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } +.ui-icon-grip-solid-vertical { background-position: -32px -224px; } +.ui-icon-grip-solid-horizontal { background-position: -48px -224px; } +.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } +.ui-icon-grip-diagonal-se { background-position: -80px -224px; } + + +/* Misc visuals +----------------------------------*/ + +/* Corner radius */ +.ui-corner-all, +.ui-corner-top, +.ui-corner-left, +.ui-corner-tl { + border-top-left-radius: 4px; +} +.ui-corner-all, +.ui-corner-top, +.ui-corner-right, +.ui-corner-tr { + border-top-right-radius: 4px; +} +.ui-corner-all, +.ui-corner-bottom, +.ui-corner-left, +.ui-corner-bl { + border-bottom-left-radius: 4px; +} +.ui-corner-all, +.ui-corner-bottom, +.ui-corner-right, +.ui-corner-br { + border-bottom-right-radius: 4px; +} + +/* Overlays */ +.ui-widget-overlay { + background: #aaaaaa url("../img/ui-bg_flat_0_aaaaaa_40x100.png") 50% 50% repeat-x; + opacity: .3; + filter: Alpha(Opacity=30); /* support: IE8 */ +} +.ui-widget-shadow { + margin: -8px 0 0 -8px; + padding: 8px; + background: #aaaaaa url("../img/ui-bg_flat_0_aaaaaa_40x100.png") 50% 50% repeat-x; + opacity: .3; + filter: Alpha(Opacity=30); /* support: IE8 */ + border-radius: 8px; +} diff --git a/img/ui-bg_flat_0_aaaaaa_40x100.png b/img/ui-bg_flat_0_aaaaaa_40x100.png new file mode 100644 index 0000000000000000000000000000000000000000..9869d1fa79112402f01a0336d933fa5c00f19c0b GIT binary patch literal 212 zcmeAS@N?(olHy`uVBq!ia0vp^8bF-F1SA+{?>A)!QcOwS?k)_>#w|r1Kptm-M`SUO z_5fqIli7AahM1>|V~EA+ zRdP`(kYX@0Ff`FMG}1LP3^BB@GBvd_G}bk+ure_C+*EQ1MMG|WN@iLmZVgTM&(r}m OFnGH9xvX?)F zK#IZ0z|ch3&`8(FFvQTp%GA`#z*5)1!pgv4c7(PNiiX_$l+3hB+!|i7PF@Gpz~JfX K=d#Wzp$P!9qBG(E literal 0 HcmV?d00001 diff --git a/img/ui-bg_glass_55_fbf9ee_1x400.png b/img/ui-bg_glass_55_fbf9ee_1x400.png new file mode 100644 index 0000000000000000000000000000000000000000..f9e28706ec062d22d5d1656383151f441da7e14c GIT binary patch literal 335 zcmeAS@N?(olHy`uVBq!ia0vp^j6gI&fCnc6a#?2AmP!?*K(O3p^r= zfwTu0yPeFo12TF&T^vI^j=w#x$i?I+((tf;UXnmgbH|3oY>pC!)f}(GR!16S-u+#{ ze6YEqRkW=8vGl=5qArKM<9}TC-}iEvB{zdaTcX5$wyRTK&AL#{d8T literal 0 HcmV?d00001 diff --git a/img/ui-bg_glass_65_ffffff_1x400.png b/img/ui-bg_glass_65_ffffff_1x400.png new file mode 100644 index 0000000000000000000000000000000000000000..02bcf0ad149466fdfd81102ca939f01de84d1775 GIT binary patch literal 207 zcmeAS@N?(olHy`uVBq!ia0vp^j6gI2NH8$CE1Q=ADW)WEcNYf6yIsOdfIQ9ukH}&m z?E%JaC$sH<3_(v9#}JM4$r%X}t&0mp9yKsb%{ak$*<@oTP*SzTHKHUXu_VRXUCGx5b?-VBQkUm|IuXOmYJrBRJgj{Vx zMbNnqUkncy+qa2-mWYc>swkcIuvGK#>(0d)B7)5f`@$Ei28nH~0h*~=;u=wsl30>z zm0Xkxq!^403{7+mjdYC+LkumfOiir}4RsAHtPBiNWK&P0;`V literal 0 HcmV?d00001 diff --git a/img/ui-bg_glass_75_e6e6e6_1x400.png b/img/ui-bg_glass_75_e6e6e6_1x400.png new file mode 100644 index 0000000000000000000000000000000000000000..4c544ef4e00d2b085d24a9c793caa5a65802c8e6 GIT binary patch literal 262 zcmeAS@N?(olHy`uVBq!ia0vp^j6gI&0LWmFTHNUZq?nSt-Ch3w7g=q17Rci)@Q5r1 z(jH*!b~4)z#PD=+46!(!TrvH)L6@80)r*_cdCvDr%)6ghVL16=s@mbz7H!uRdGeDa z?kzLg)16i!f8fKx84s0>4hUVThrHm8q$ffu*j2g_VK9>nc6a#?2AmP!?*K(O3p^r= zfwTu0yPeFo12VciT^vI^j=w#>k(V)1qW$CZ|6)SVV-&*#dav<$DMuV&n0Dbpw@al#>C85n$S hDmjFrAvZrIGp!Q0hNk;x>VO&;JYD@<);T3K0RZU>bjAPx literal 0 HcmV?d00001 diff --git a/img/ui-bg_highlight-soft_75_cccccc_1x100.png b/img/ui-bg_highlight-soft_75_cccccc_1x100.png new file mode 100644 index 0000000000000000000000000000000000000000..bdf5d2c6987ffa4e119729a46176a613602dd278 GIT binary patch literal 280 zcmeAS@N?(olHy`uVBq!ia0vp^j6j?s03;ZUuHXC*q?nSt-Ch3w7g=q17Rci)@Q5r1 z(jH*!b~4)z$cXZEaSV~ToLo`U+vu0Ue0cG9p8hWqa?gxxGLm=1A1u)Cewe3oSeCaf zI$k30UHXoTXA5lSJe(zTcE%W-S*bfB&J`pw9sa4-R?IGW?p~6`>jMSP&M+u3 zY@9al)zrvpHlQu4C9V-ADTyViR>?)FK#IZ0z|ch3&`8(FFvQTp%GA`#&{)^N!pgwl ib5qG76b-rgDVb@NxHUB0KT`+Pz~JfX=d#Wzp$PzC-dnf; literal 0 HcmV?d00001 diff --git a/img/ui-icons_222222_256x240.png b/img/ui-icons_222222_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..c1cb1170c8b3795835b8831ab81fa9ae63b606b1 GIT binary patch literal 6922 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 QJ~;stWz}Trq%1=J3#jBGg8%>k literal 0 HcmV?d00001 diff --git a/img/ui-icons_2e83ff_256x240.png b/img/ui-icons_2e83ff_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..84b601bf0f726bf95801da487deaf2344a32e4b8 GIT binary patch literal 4549 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 F{{S81aohj^ literal 0 HcmV?d00001 diff --git a/img/ui-icons_454545_256x240.png b/img/ui-icons_454545_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..b6db1acdd433be80a472b045018f25c7f2cf7e08 GIT binary patch literal 6992 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 literal 0 HcmV?d00001 diff --git a/img/ui-icons_cd0a0a_256x240.png b/img/ui-icons_cd0a0a_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..ed5b6b0930f672fa08e9b9bdbe5e55370fd1dc30 GIT binary patch literal 4549 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 DTfr$v literal 0 HcmV?d00001 diff --git a/inc/headerAdmin.inc.php b/inc/headerAdmin.inc.php index 63e6bfe9..403c68df 100644 --- a/inc/headerAdmin.inc.php +++ b/inc/headerAdmin.inc.php @@ -47,6 +47,9 @@ require(HESK_PATH . 'modsForHesk_settings.inc.php'); + + + @@ -58,6 +61,7 @@ require(HESK_PATH . 'modsForHesk_settings.inc.php'); + diff --git a/js/jquery-ui.min.js b/js/jquery-ui.min.js new file mode 100644 index 00000000..de977872 --- /dev/null +++ b/js/jquery-ui.min.js @@ -0,0 +1,13 @@ +/*! jQuery UI - v1.11.2 - 2014-12-21 +* http://jqueryui.com +* Includes: core.js, widget.js, mouse.js, position.js, draggable.js, droppable.js, resizable.js, selectable.js, sortable.js, accordion.js, autocomplete.js, button.js, datepicker.js, dialog.js, menu.js, progressbar.js, selectmenu.js, slider.js, spinner.js, tabs.js, tooltip.js, effect.js, effect-blind.js, effect-bounce.js, effect-clip.js, effect-drop.js, effect-explode.js, effect-fade.js, effect-fold.js, effect-highlight.js, effect-puff.js, effect-pulsate.js, effect-scale.js, effect-shake.js, effect-size.js, effect-slide.js, effect-transfer.js +* Copyright 2014 jQuery Foundation and other contributors; Licensed MIT */ + +(function(e){"function"==typeof define&&define.amd?define(["jquery"],e):e(jQuery)})(function(e){function t(t,s){var n,a,o,r=t.nodeName.toLowerCase();return"area"===r?(n=t.parentNode,a=n.name,t.href&&a&&"map"===n.nodeName.toLowerCase()?(o=e("img[usemap='#"+a+"']")[0],!!o&&i(o)):!1):(/input|select|textarea|button|object/.test(r)?!t.disabled:"a"===r?t.href||s:s)&&i(t)}function i(t){return e.expr.filters.visible(t)&&!e(t).parents().addBack().filter(function(){return"hidden"===e.css(this,"visibility")}).length}function s(e){for(var t,i;e.length&&e[0]!==document;){if(t=e.css("position"),("absolute"===t||"relative"===t||"fixed"===t)&&(i=parseInt(e.css("zIndex"),10),!isNaN(i)&&0!==i))return i;e=e.parent()}return 0}function n(){this._curInst=null,this._keyEvent=!1,this._disabledInputs=[],this._datepickerShowing=!1,this._inDialog=!1,this._mainDivId="ui-datepicker-div",this._inlineClass="ui-datepicker-inline",this._appendClass="ui-datepicker-append",this._triggerClass="ui-datepicker-trigger",this._dialogClass="ui-datepicker-dialog",this._disableClass="ui-datepicker-disabled",this._unselectableClass="ui-datepicker-unselectable",this._currentClass="ui-datepicker-current-day",this._dayOverClass="ui-datepicker-days-cell-over",this.regional=[],this.regional[""]={closeText:"Done",prevText:"Prev",nextText:"Next",currentText:"Today",monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su","Mo","Tu","We","Th","Fr","Sa"],weekHeader:"Wk",dateFormat:"mm/dd/yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""},this._defaults={showOn:"focus",showAnim:"fadeIn",showOptions:{},defaultDate:null,appendText:"",buttonText:"...",buttonImage:"",buttonImageOnly:!1,hideIfNoPrevNext:!1,navigationAsDateFormat:!1,gotoCurrent:!1,changeMonth:!1,changeYear:!1,yearRange:"c-10:c+10",showOtherMonths:!1,selectOtherMonths:!1,showWeek:!1,calculateWeek:this.iso8601Week,shortYearCutoff:"+10",minDate:null,maxDate:null,duration:"fast",beforeShowDay:null,beforeShow:null,onSelect:null,onChangeMonthYear:null,onClose:null,numberOfMonths:1,showCurrentAtPos:0,stepMonths:1,stepBigMonths:12,altField:"",altFormat:"",constrainInput:!0,showButtonPanel:!1,autoSize:!1,disabled:!1},e.extend(this._defaults,this.regional[""]),this.regional.en=e.extend(!0,{},this.regional[""]),this.regional["en-US"]=e.extend(!0,{},this.regional.en),this.dpDiv=a(e("
    "))}function a(t){var i="button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";return t.delegate(i,"mouseout",function(){e(this).removeClass("ui-state-hover"),-1!==this.className.indexOf("ui-datepicker-prev")&&e(this).removeClass("ui-datepicker-prev-hover"),-1!==this.className.indexOf("ui-datepicker-next")&&e(this).removeClass("ui-datepicker-next-hover")}).delegate(i,"mouseover",o)}function o(){e.datepicker._isDisabledDatepicker(v.inline?v.dpDiv.parent()[0]:v.input[0])||(e(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover"),e(this).addClass("ui-state-hover"),-1!==this.className.indexOf("ui-datepicker-prev")&&e(this).addClass("ui-datepicker-prev-hover"),-1!==this.className.indexOf("ui-datepicker-next")&&e(this).addClass("ui-datepicker-next-hover"))}function r(t,i){e.extend(t,i);for(var s in i)null==i[s]&&(t[s]=i[s]);return t}function h(e){return function(){var t=this.element.val();e.apply(this,arguments),this._refresh(),t!==this.element.val()&&this._trigger("change")}}e.ui=e.ui||{},e.extend(e.ui,{version:"1.11.2",keyCode:{BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38}}),e.fn.extend({scrollParent:function(t){var i=this.css("position"),s="absolute"===i,n=t?/(auto|scroll|hidden)/:/(auto|scroll)/,a=this.parents().filter(function(){var t=e(this);return s&&"static"===t.css("position")?!1:n.test(t.css("overflow")+t.css("overflow-y")+t.css("overflow-x"))}).eq(0);return"fixed"!==i&&a.length?a:e(this[0].ownerDocument||document)},uniqueId:function(){var e=0;return function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++e)})}}(),removeUniqueId:function(){return this.each(function(){/^ui-id-\d+$/.test(this.id)&&e(this).removeAttr("id")})}}),e.extend(e.expr[":"],{data:e.expr.createPseudo?e.expr.createPseudo(function(t){return function(i){return!!e.data(i,t)}}):function(t,i,s){return!!e.data(t,s[3])},focusable:function(i){return t(i,!isNaN(e.attr(i,"tabindex")))},tabbable:function(i){var s=e.attr(i,"tabindex"),n=isNaN(s);return(n||s>=0)&&t(i,!n)}}),e("").outerWidth(1).jquery||e.each(["Width","Height"],function(t,i){function s(t,i,s,a){return e.each(n,function(){i-=parseFloat(e.css(t,"padding"+this))||0,s&&(i-=parseFloat(e.css(t,"border"+this+"Width"))||0),a&&(i-=parseFloat(e.css(t,"margin"+this))||0)}),i}var n="Width"===i?["Left","Right"]:["Top","Bottom"],a=i.toLowerCase(),o={innerWidth:e.fn.innerWidth,innerHeight:e.fn.innerHeight,outerWidth:e.fn.outerWidth,outerHeight:e.fn.outerHeight};e.fn["inner"+i]=function(t){return void 0===t?o["inner"+i].call(this):this.each(function(){e(this).css(a,s(this,t)+"px")})},e.fn["outer"+i]=function(t,n){return"number"!=typeof t?o["outer"+i].call(this,t):this.each(function(){e(this).css(a,s(this,t,!0,n)+"px")})}}),e.fn.addBack||(e.fn.addBack=function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}),e("").data("a-b","a").removeData("a-b").data("a-b")&&(e.fn.removeData=function(t){return function(i){return arguments.length?t.call(this,e.camelCase(i)):t.call(this)}}(e.fn.removeData)),e.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase()),e.fn.extend({focus:function(t){return function(i,s){return"number"==typeof i?this.each(function(){var t=this;setTimeout(function(){e(t).focus(),s&&s.call(t)},i)}):t.apply(this,arguments)}}(e.fn.focus),disableSelection:function(){var e="onselectstart"in document.createElement("div")?"selectstart":"mousedown";return function(){return this.bind(e+".ui-disableSelection",function(e){e.preventDefault()})}}(),enableSelection:function(){return this.unbind(".ui-disableSelection")},zIndex:function(t){if(void 0!==t)return this.css("zIndex",t);if(this.length)for(var i,s,n=e(this[0]);n.length&&n[0]!==document;){if(i=n.css("position"),("absolute"===i||"relative"===i||"fixed"===i)&&(s=parseInt(n.css("zIndex"),10),!isNaN(s)&&0!==s))return s;n=n.parent()}return 0}}),e.ui.plugin={add:function(t,i,s){var n,a=e.ui[t].prototype;for(n in s)a.plugins[n]=a.plugins[n]||[],a.plugins[n].push([i,s[n]])},call:function(e,t,i,s){var n,a=e.plugins[t];if(a&&(s||e.element[0].parentNode&&11!==e.element[0].parentNode.nodeType))for(n=0;a.length>n;n++)e.options[a[n][0]]&&a[n][1].apply(e.element,i)}};var l=0,u=Array.prototype.slice;e.cleanData=function(t){return function(i){var s,n,a;for(a=0;null!=(n=i[a]);a++)try{s=e._data(n,"events"),s&&s.remove&&e(n).triggerHandler("remove")}catch(o){}t(i)}}(e.cleanData),e.widget=function(t,i,s){var n,a,o,r,h={},l=t.split(".")[0];return t=t.split(".")[1],n=l+"-"+t,s||(s=i,i=e.Widget),e.expr[":"][n.toLowerCase()]=function(t){return!!e.data(t,n)},e[l]=e[l]||{},a=e[l][t],o=e[l][t]=function(e,t){return this._createWidget?(arguments.length&&this._createWidget(e,t),void 0):new o(e,t)},e.extend(o,a,{version:s.version,_proto:e.extend({},s),_childConstructors:[]}),r=new i,r.options=e.widget.extend({},r.options),e.each(s,function(t,s){return e.isFunction(s)?(h[t]=function(){var e=function(){return i.prototype[t].apply(this,arguments)},n=function(e){return i.prototype[t].apply(this,e)};return function(){var t,i=this._super,a=this._superApply;return this._super=e,this._superApply=n,t=s.apply(this,arguments),this._super=i,this._superApply=a,t}}(),void 0):(h[t]=s,void 0)}),o.prototype=e.widget.extend(r,{widgetEventPrefix:a?r.widgetEventPrefix||t:t},h,{constructor:o,namespace:l,widgetName:t,widgetFullName:n}),a?(e.each(a._childConstructors,function(t,i){var s=i.prototype;e.widget(s.namespace+"."+s.widgetName,o,i._proto)}),delete a._childConstructors):i._childConstructors.push(o),e.widget.bridge(t,o),o},e.widget.extend=function(t){for(var i,s,n=u.call(arguments,1),a=0,o=n.length;o>a;a++)for(i in n[a])s=n[a][i],n[a].hasOwnProperty(i)&&void 0!==s&&(t[i]=e.isPlainObject(s)?e.isPlainObject(t[i])?e.widget.extend({},t[i],s):e.widget.extend({},s):s);return t},e.widget.bridge=function(t,i){var s=i.prototype.widgetFullName||t;e.fn[t]=function(n){var a="string"==typeof n,o=u.call(arguments,1),r=this;return n=!a&&o.length?e.widget.extend.apply(null,[n].concat(o)):n,a?this.each(function(){var i,a=e.data(this,s);return"instance"===n?(r=a,!1):a?e.isFunction(a[n])&&"_"!==n.charAt(0)?(i=a[n].apply(a,o),i!==a&&void 0!==i?(r=i&&i.jquery?r.pushStack(i.get()):i,!1):void 0):e.error("no such method '"+n+"' for "+t+" widget instance"):e.error("cannot call methods on "+t+" prior to initialization; "+"attempted to call method '"+n+"'")}):this.each(function(){var t=e.data(this,s);t?(t.option(n||{}),t._init&&t._init()):e.data(this,s,new i(n,this))}),r}},e.Widget=function(){},e.Widget._childConstructors=[],e.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"
    ",options:{disabled:!1,create:null},_createWidget:function(t,i){i=e(i||this.defaultElement||this)[0],this.element=e(i),this.uuid=l++,this.eventNamespace="."+this.widgetName+this.uuid,this.bindings=e(),this.hoverable=e(),this.focusable=e(),i!==this&&(e.data(i,this.widgetFullName,this),this._on(!0,this.element,{remove:function(e){e.target===i&&this.destroy()}}),this.document=e(i.style?i.ownerDocument:i.document||i),this.window=e(this.document[0].defaultView||this.document[0].parentWindow)),this.options=e.widget.extend({},this.options,this._getCreateOptions(),t),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:e.noop,_getCreateEventData:e.noop,_create:e.noop,_init:e.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetFullName).removeData(e.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled "+"ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:e.noop,widget:function(){return this.element},option:function(t,i){var s,n,a,o=t;if(0===arguments.length)return e.widget.extend({},this.options);if("string"==typeof t)if(o={},s=t.split("."),t=s.shift(),s.length){for(n=o[t]=e.widget.extend({},this.options[t]),a=0;s.length-1>a;a++)n[s[a]]=n[s[a]]||{},n=n[s[a]];if(t=s.pop(),1===arguments.length)return void 0===n[t]?null:n[t];n[t]=i}else{if(1===arguments.length)return void 0===this.options[t]?null:this.options[t];o[t]=i}return this._setOptions(o),this},_setOptions:function(e){var t;for(t in e)this._setOption(t,e[t]);return this},_setOption:function(e,t){return this.options[e]=t,"disabled"===e&&(this.widget().toggleClass(this.widgetFullName+"-disabled",!!t),t&&(this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus"))),this},enable:function(){return this._setOptions({disabled:!1})},disable:function(){return this._setOptions({disabled:!0})},_on:function(t,i,s){var n,a=this;"boolean"!=typeof t&&(s=i,i=t,t=!1),s?(i=n=e(i),this.bindings=this.bindings.add(i)):(s=i,i=this.element,n=this.widget()),e.each(s,function(s,o){function r(){return t||a.options.disabled!==!0&&!e(this).hasClass("ui-state-disabled")?("string"==typeof o?a[o]:o).apply(a,arguments):void 0}"string"!=typeof o&&(r.guid=o.guid=o.guid||r.guid||e.guid++);var h=s.match(/^([\w:-]*)\s*(.*)$/),l=h[1]+a.eventNamespace,u=h[2];u?n.delegate(u,l,r):i.bind(l,r)})},_off:function(t,i){i=(i||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,t.unbind(i).undelegate(i),this.bindings=e(this.bindings.not(t).get()),this.focusable=e(this.focusable.not(t).get()),this.hoverable=e(this.hoverable.not(t).get())},_delay:function(e,t){function i(){return("string"==typeof e?s[e]:e).apply(s,arguments)}var s=this;return setTimeout(i,t||0)},_hoverable:function(t){this.hoverable=this.hoverable.add(t),this._on(t,{mouseenter:function(t){e(t.currentTarget).addClass("ui-state-hover")},mouseleave:function(t){e(t.currentTarget).removeClass("ui-state-hover")}})},_focusable:function(t){this.focusable=this.focusable.add(t),this._on(t,{focusin:function(t){e(t.currentTarget).addClass("ui-state-focus")},focusout:function(t){e(t.currentTarget).removeClass("ui-state-focus")}})},_trigger:function(t,i,s){var n,a,o=this.options[t];if(s=s||{},i=e.Event(i),i.type=(t===this.widgetEventPrefix?t:this.widgetEventPrefix+t).toLowerCase(),i.target=this.element[0],a=i.originalEvent)for(n in a)n in i||(i[n]=a[n]);return this.element.trigger(i,s),!(e.isFunction(o)&&o.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},e.each({show:"fadeIn",hide:"fadeOut"},function(t,i){e.Widget.prototype["_"+t]=function(s,n,a){"string"==typeof n&&(n={effect:n});var o,r=n?n===!0||"number"==typeof n?i:n.effect||i:t;n=n||{},"number"==typeof n&&(n={duration:n}),o=!e.isEmptyObject(n),n.complete=a,n.delay&&s.delay(n.delay),o&&e.effects&&e.effects.effect[r]?s[t](n):r!==t&&s[r]?s[r](n.duration,n.easing,a):s.queue(function(i){e(this)[t](),a&&a.call(s[0]),i()})}}),e.widget;var d=!1;e(document).mouseup(function(){d=!1}),e.widget("ui.mouse",{version:"1.11.2",options:{cancel:"input,textarea,button,select,option",distance:1,delay:0},_mouseInit:function(){var t=this;this.element.bind("mousedown."+this.widgetName,function(e){return t._mouseDown(e)}).bind("click."+this.widgetName,function(i){return!0===e.data(i.target,t.widgetName+".preventClickEvent")?(e.removeData(i.target,t.widgetName+".preventClickEvent"),i.stopImmediatePropagation(),!1):void 0}),this.started=!1},_mouseDestroy:function(){this.element.unbind("."+this.widgetName),this._mouseMoveDelegate&&this.document.unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(t){if(!d){this._mouseMoved=!1,this._mouseStarted&&this._mouseUp(t),this._mouseDownEvent=t;var i=this,s=1===t.which,n="string"==typeof this.options.cancel&&t.target.nodeName?e(t.target).closest(this.options.cancel).length:!1;return s&&!n&&this._mouseCapture(t)?(this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){i.mouseDelayMet=!0},this.options.delay)),this._mouseDistanceMet(t)&&this._mouseDelayMet(t)&&(this._mouseStarted=this._mouseStart(t)!==!1,!this._mouseStarted)?(t.preventDefault(),!0):(!0===e.data(t.target,this.widgetName+".preventClickEvent")&&e.removeData(t.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(e){return i._mouseMove(e)},this._mouseUpDelegate=function(e){return i._mouseUp(e)},this.document.bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate),t.preventDefault(),d=!0,!0)):!0}},_mouseMove:function(t){if(this._mouseMoved){if(e.ui.ie&&(!document.documentMode||9>document.documentMode)&&!t.button)return this._mouseUp(t);if(!t.which)return this._mouseUp(t)}return(t.which||t.button)&&(this._mouseMoved=!0),this._mouseStarted?(this._mouseDrag(t),t.preventDefault()):(this._mouseDistanceMet(t)&&this._mouseDelayMet(t)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,t)!==!1,this._mouseStarted?this._mouseDrag(t):this._mouseUp(t)),!this._mouseStarted)},_mouseUp:function(t){return this.document.unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,t.target===this._mouseDownEvent.target&&e.data(t.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(t)),d=!1,!1},_mouseDistanceMet:function(e){return Math.max(Math.abs(this._mouseDownEvent.pageX-e.pageX),Math.abs(this._mouseDownEvent.pageY-e.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}}),function(){function t(e,t,i){return[parseFloat(e[0])*(p.test(e[0])?t/100:1),parseFloat(e[1])*(p.test(e[1])?i/100:1)]}function i(t,i){return parseInt(e.css(t,i),10)||0}function s(t){var i=t[0];return 9===i.nodeType?{width:t.width(),height:t.height(),offset:{top:0,left:0}}:e.isWindow(i)?{width:t.width(),height:t.height(),offset:{top:t.scrollTop(),left:t.scrollLeft()}}:i.preventDefault?{width:0,height:0,offset:{top:i.pageY,left:i.pageX}}:{width:t.outerWidth(),height:t.outerHeight(),offset:t.offset()}}e.ui=e.ui||{};var n,a,o=Math.max,r=Math.abs,h=Math.round,l=/left|center|right/,u=/top|center|bottom/,d=/[\+\-]\d+(\.[\d]+)?%?/,c=/^\w+/,p=/%$/,f=e.fn.position;e.position={scrollbarWidth:function(){if(void 0!==n)return n;var t,i,s=e("
    "),a=s.children()[0];return e("body").append(s),t=a.offsetWidth,s.css("overflow","scroll"),i=a.offsetWidth,t===i&&(i=s[0].clientWidth),s.remove(),n=t-i},getScrollInfo:function(t){var i=t.isWindow||t.isDocument?"":t.element.css("overflow-x"),s=t.isWindow||t.isDocument?"":t.element.css("overflow-y"),n="scroll"===i||"auto"===i&&t.widthi?"left":t>0?"right":"center",vertical:0>a?"top":s>0?"bottom":"middle"};d>m&&m>r(t+i)&&(h.horizontal="center"),c>g&&g>r(s+a)&&(h.vertical="middle"),h.important=o(r(t),r(i))>o(r(s),r(a))?"horizontal":"vertical",n.using.call(this,e,h)}),u.offset(e.extend(M,{using:l}))})},e.ui.position={fit:{left:function(e,t){var i,s=t.within,n=s.isWindow?s.scrollLeft:s.offset.left,a=s.width,r=e.left-t.collisionPosition.marginLeft,h=n-r,l=r+t.collisionWidth-a-n;t.collisionWidth>a?h>0&&0>=l?(i=e.left+h+t.collisionWidth-a-n,e.left+=h-i):e.left=l>0&&0>=h?n:h>l?n+a-t.collisionWidth:n:h>0?e.left+=h:l>0?e.left-=l:e.left=o(e.left-r,e.left)},top:function(e,t){var i,s=t.within,n=s.isWindow?s.scrollTop:s.offset.top,a=t.within.height,r=e.top-t.collisionPosition.marginTop,h=n-r,l=r+t.collisionHeight-a-n;t.collisionHeight>a?h>0&&0>=l?(i=e.top+h+t.collisionHeight-a-n,e.top+=h-i):e.top=l>0&&0>=h?n:h>l?n+a-t.collisionHeight:n:h>0?e.top+=h:l>0?e.top-=l:e.top=o(e.top-r,e.top)}},flip:{left:function(e,t){var i,s,n=t.within,a=n.offset.left+n.scrollLeft,o=n.width,h=n.isWindow?n.scrollLeft:n.offset.left,l=e.left-t.collisionPosition.marginLeft,u=l-h,d=l+t.collisionWidth-o-h,c="left"===t.my[0]?-t.elemWidth:"right"===t.my[0]?t.elemWidth:0,p="left"===t.at[0]?t.targetWidth:"right"===t.at[0]?-t.targetWidth:0,f=-2*t.offset[0];0>u?(i=e.left+c+p+f+t.collisionWidth-o-a,(0>i||r(u)>i)&&(e.left+=c+p+f)):d>0&&(s=e.left-t.collisionPosition.marginLeft+c+p+f-h,(s>0||d>r(s))&&(e.left+=c+p+f))},top:function(e,t){var i,s,n=t.within,a=n.offset.top+n.scrollTop,o=n.height,h=n.isWindow?n.scrollTop:n.offset.top,l=e.top-t.collisionPosition.marginTop,u=l-h,d=l+t.collisionHeight-o-h,c="top"===t.my[1],p=c?-t.elemHeight:"bottom"===t.my[1]?t.elemHeight:0,f="top"===t.at[1]?t.targetHeight:"bottom"===t.at[1]?-t.targetHeight:0,m=-2*t.offset[1];0>u?(s=e.top+p+f+m+t.collisionHeight-o-a,e.top+p+f+m>u&&(0>s||r(u)>s)&&(e.top+=p+f+m)):d>0&&(i=e.top-t.collisionPosition.marginTop+p+f+m-h,e.top+p+f+m>d&&(i>0||d>r(i))&&(e.top+=p+f+m))}},flipfit:{left:function(){e.ui.position.flip.left.apply(this,arguments),e.ui.position.fit.left.apply(this,arguments)},top:function(){e.ui.position.flip.top.apply(this,arguments),e.ui.position.fit.top.apply(this,arguments)}}},function(){var t,i,s,n,o,r=document.getElementsByTagName("body")[0],h=document.createElement("div");t=document.createElement(r?"div":"body"),s={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"},r&&e.extend(s,{position:"absolute",left:"-1000px",top:"-1000px"});for(o in s)t.style[o]=s[o];t.appendChild(h),i=r||document.documentElement,i.insertBefore(t,i.firstChild),h.style.cssText="position: absolute; left: 10.7432222px;",n=e(h).offset().left,a=n>10&&11>n,t.innerHTML="",i.removeChild(t)}()}(),e.ui.position,e.widget("ui.draggable",e.ui.mouse,{version:"1.11.2",widgetEventPrefix:"drag",options:{addClasses:!0,appendTo:"parent",axis:!1,connectToSortable:!1,containment:!1,cursor:"auto",cursorAt:!1,grid:!1,handle:!1,helper:"original",iframeFix:!1,opacity:!1,refreshPositions:!1,revert:!1,revertDuration:500,scope:"default",scroll:!0,scrollSensitivity:20,scrollSpeed:20,snap:!1,snapMode:"both",snapTolerance:20,stack:!1,zIndex:!1,drag:null,start:null,stop:null},_create:function(){"original"===this.options.helper&&this._setPositionRelative(),this.options.addClasses&&this.element.addClass("ui-draggable"),this.options.disabled&&this.element.addClass("ui-draggable-disabled"),this._setHandleClassName(),this._mouseInit()},_setOption:function(e,t){this._super(e,t),"handle"===e&&(this._removeHandleClassName(),this._setHandleClassName())},_destroy:function(){return(this.helper||this.element).is(".ui-draggable-dragging")?(this.destroyOnClear=!0,void 0):(this.element.removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled"),this._removeHandleClassName(),this._mouseDestroy(),void 0)},_mouseCapture:function(t){var i=this.options;return this._blurActiveElement(t),this.helper||i.disabled||e(t.target).closest(".ui-resizable-handle").length>0?!1:(this.handle=this._getHandle(t),this.handle?(this._blockFrames(i.iframeFix===!0?"iframe":i.iframeFix),!0):!1)},_blockFrames:function(t){this.iframeBlocks=this.document.find(t).map(function(){var t=e(this);return e("
    ").css("position","absolute").appendTo(t.parent()).outerWidth(t.outerWidth()).outerHeight(t.outerHeight()).offset(t.offset())[0]})},_unblockFrames:function(){this.iframeBlocks&&(this.iframeBlocks.remove(),delete this.iframeBlocks)},_blurActiveElement:function(t){var i=this.document[0];if(this.handleElement.is(t.target))try{i.activeElement&&"body"!==i.activeElement.nodeName.toLowerCase()&&e(i.activeElement).blur()}catch(s){}},_mouseStart:function(t){var i=this.options;return this.helper=this._createHelper(t),this.helper.addClass("ui-draggable-dragging"),this._cacheHelperProportions(),e.ui.ddmanager&&(e.ui.ddmanager.current=this),this._cacheMargins(),this.cssPosition=this.helper.css("position"),this.scrollParent=this.helper.scrollParent(!0),this.offsetParent=this.helper.offsetParent(),this.hasFixedAncestor=this.helper.parents().filter(function(){return"fixed"===e(this).css("position")}).length>0,this.positionAbs=this.element.offset(),this._refreshOffsets(t),this.originalPosition=this.position=this._generatePosition(t,!1),this.originalPageX=t.pageX,this.originalPageY=t.pageY,i.cursorAt&&this._adjustOffsetFromHelper(i.cursorAt),this._setContainment(),this._trigger("start",t)===!1?(this._clear(),!1):(this._cacheHelperProportions(),e.ui.ddmanager&&!i.dropBehaviour&&e.ui.ddmanager.prepareOffsets(this,t),this._normalizeRightBottom(),this._mouseDrag(t,!0),e.ui.ddmanager&&e.ui.ddmanager.dragStart(this,t),!0)},_refreshOffsets:function(e){this.offset={top:this.positionAbs.top-this.margins.top,left:this.positionAbs.left-this.margins.left,scroll:!1,parent:this._getParentOffset(),relative:this._getRelativeOffset()},this.offset.click={left:e.pageX-this.offset.left,top:e.pageY-this.offset.top}},_mouseDrag:function(t,i){if(this.hasFixedAncestor&&(this.offset.parent=this._getParentOffset()),this.position=this._generatePosition(t,!0),this.positionAbs=this._convertPositionTo("absolute"),!i){var s=this._uiHash();if(this._trigger("drag",t,s)===!1)return this._mouseUp({}),!1;this.position=s.position}return this.helper[0].style.left=this.position.left+"px",this.helper[0].style.top=this.position.top+"px",e.ui.ddmanager&&e.ui.ddmanager.drag(this,t),!1},_mouseStop:function(t){var i=this,s=!1;return e.ui.ddmanager&&!this.options.dropBehaviour&&(s=e.ui.ddmanager.drop(this,t)),this.dropped&&(s=this.dropped,this.dropped=!1),"invalid"===this.options.revert&&!s||"valid"===this.options.revert&&s||this.options.revert===!0||e.isFunction(this.options.revert)&&this.options.revert.call(this.element,s)?e(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){i._trigger("stop",t)!==!1&&i._clear()}):this._trigger("stop",t)!==!1&&this._clear(),!1},_mouseUp:function(t){return this._unblockFrames(),e.ui.ddmanager&&e.ui.ddmanager.dragStop(this,t),this.handleElement.is(t.target)&&this.element.focus(),e.ui.mouse.prototype._mouseUp.call(this,t)},cancel:function(){return this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear(),this},_getHandle:function(t){return this.options.handle?!!e(t.target).closest(this.element.find(this.options.handle)).length:!0},_setHandleClassName:function(){this.handleElement=this.options.handle?this.element.find(this.options.handle):this.element,this.handleElement.addClass("ui-draggable-handle")},_removeHandleClassName:function(){this.handleElement.removeClass("ui-draggable-handle")},_createHelper:function(t){var i=this.options,s=e.isFunction(i.helper),n=s?e(i.helper.apply(this.element[0],[t])):"clone"===i.helper?this.element.clone().removeAttr("id"):this.element;return n.parents("body").length||n.appendTo("parent"===i.appendTo?this.element[0].parentNode:i.appendTo),s&&n[0]===this.element[0]&&this._setPositionRelative(),n[0]===this.element[0]||/(fixed|absolute)/.test(n.css("position"))||n.css("position","absolute"),n},_setPositionRelative:function(){/^(?:r|a|f)/.test(this.element.css("position"))||(this.element[0].style.position="relative")},_adjustOffsetFromHelper:function(t){"string"==typeof t&&(t=t.split(" ")),e.isArray(t)&&(t={left:+t[0],top:+t[1]||0}),"left"in t&&(this.offset.click.left=t.left+this.margins.left),"right"in t&&(this.offset.click.left=this.helperProportions.width-t.right+this.margins.left),"top"in t&&(this.offset.click.top=t.top+this.margins.top),"bottom"in t&&(this.offset.click.top=this.helperProportions.height-t.bottom+this.margins.top)},_isRootNode:function(e){return/(html|body)/i.test(e.tagName)||e===this.document[0]},_getParentOffset:function(){var t=this.offsetParent.offset(),i=this.document[0];return"absolute"===this.cssPosition&&this.scrollParent[0]!==i&&e.contains(this.scrollParent[0],this.offsetParent[0])&&(t.left+=this.scrollParent.scrollLeft(),t.top+=this.scrollParent.scrollTop()),this._isRootNode(this.offsetParent[0])&&(t={top:0,left:0}),{top:t.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:t.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if("relative"!==this.cssPosition)return{top:0,left:0};var e=this.element.position(),t=this._isRootNode(this.scrollParent[0]);return{top:e.top-(parseInt(this.helper.css("top"),10)||0)+(t?0:this.scrollParent.scrollTop()),left:e.left-(parseInt(this.helper.css("left"),10)||0)+(t?0:this.scrollParent.scrollLeft())}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0,right:parseInt(this.element.css("marginRight"),10)||0,bottom:parseInt(this.element.css("marginBottom"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var t,i,s,n=this.options,a=this.document[0];return this.relativeContainer=null,n.containment?"window"===n.containment?(this.containment=[e(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,e(window).scrollTop()-this.offset.relative.top-this.offset.parent.top,e(window).scrollLeft()+e(window).width()-this.helperProportions.width-this.margins.left,e(window).scrollTop()+(e(window).height()||a.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top],void 0):"document"===n.containment?(this.containment=[0,0,e(a).width()-this.helperProportions.width-this.margins.left,(e(a).height()||a.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top],void 0):n.containment.constructor===Array?(this.containment=n.containment,void 0):("parent"===n.containment&&(n.containment=this.helper[0].parentNode),i=e(n.containment),s=i[0],s&&(t=/(scroll|auto)/.test(i.css("overflow")),this.containment=[(parseInt(i.css("borderLeftWidth"),10)||0)+(parseInt(i.css("paddingLeft"),10)||0),(parseInt(i.css("borderTopWidth"),10)||0)+(parseInt(i.css("paddingTop"),10)||0),(t?Math.max(s.scrollWidth,s.offsetWidth):s.offsetWidth)-(parseInt(i.css("borderRightWidth"),10)||0)-(parseInt(i.css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(t?Math.max(s.scrollHeight,s.offsetHeight):s.offsetHeight)-(parseInt(i.css("borderBottomWidth"),10)||0)-(parseInt(i.css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom],this.relativeContainer=i),void 0):(this.containment=null,void 0)},_convertPositionTo:function(e,t){t||(t=this.position);var i="absolute"===e?1:-1,s=this._isRootNode(this.scrollParent[0]);return{top:t.top+this.offset.relative.top*i+this.offset.parent.top*i-("fixed"===this.cssPosition?-this.offset.scroll.top:s?0:this.offset.scroll.top)*i,left:t.left+this.offset.relative.left*i+this.offset.parent.left*i-("fixed"===this.cssPosition?-this.offset.scroll.left:s?0:this.offset.scroll.left)*i}},_generatePosition:function(e,t){var i,s,n,a,o=this.options,r=this._isRootNode(this.scrollParent[0]),h=e.pageX,l=e.pageY;return r&&this.offset.scroll||(this.offset.scroll={top:this.scrollParent.scrollTop(),left:this.scrollParent.scrollLeft()}),t&&(this.containment&&(this.relativeContainer?(s=this.relativeContainer.offset(),i=[this.containment[0]+s.left,this.containment[1]+s.top,this.containment[2]+s.left,this.containment[3]+s.top]):i=this.containment,e.pageX-this.offset.click.lefti[2]&&(h=i[2]+this.offset.click.left),e.pageY-this.offset.click.top>i[3]&&(l=i[3]+this.offset.click.top)),o.grid&&(n=o.grid[1]?this.originalPageY+Math.round((l-this.originalPageY)/o.grid[1])*o.grid[1]:this.originalPageY,l=i?n-this.offset.click.top>=i[1]||n-this.offset.click.top>i[3]?n:n-this.offset.click.top>=i[1]?n-o.grid[1]:n+o.grid[1]:n,a=o.grid[0]?this.originalPageX+Math.round((h-this.originalPageX)/o.grid[0])*o.grid[0]:this.originalPageX,h=i?a-this.offset.click.left>=i[0]||a-this.offset.click.left>i[2]?a:a-this.offset.click.left>=i[0]?a-o.grid[0]:a+o.grid[0]:a),"y"===o.axis&&(h=this.originalPageX),"x"===o.axis&&(l=this.originalPageY)),{top:l-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.offset.scroll.top:r?0:this.offset.scroll.top),left:h-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.offset.scroll.left:r?0:this.offset.scroll.left)} +},_clear:function(){this.helper.removeClass("ui-draggable-dragging"),this.helper[0]===this.element[0]||this.cancelHelperRemoval||this.helper.remove(),this.helper=null,this.cancelHelperRemoval=!1,this.destroyOnClear&&this.destroy()},_normalizeRightBottom:function(){"y"!==this.options.axis&&"auto"!==this.helper.css("right")&&(this.helper.width(this.helper.width()),this.helper.css("right","auto")),"x"!==this.options.axis&&"auto"!==this.helper.css("bottom")&&(this.helper.height(this.helper.height()),this.helper.css("bottom","auto"))},_trigger:function(t,i,s){return s=s||this._uiHash(),e.ui.plugin.call(this,t,[i,s,this],!0),/^(drag|start|stop)/.test(t)&&(this.positionAbs=this._convertPositionTo("absolute"),s.offset=this.positionAbs),e.Widget.prototype._trigger.call(this,t,i,s)},plugins:{},_uiHash:function(){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}}),e.ui.plugin.add("draggable","connectToSortable",{start:function(t,i,s){var n=e.extend({},i,{item:s.element});s.sortables=[],e(s.options.connectToSortable).each(function(){var i=e(this).sortable("instance");i&&!i.options.disabled&&(s.sortables.push(i),i.refreshPositions(),i._trigger("activate",t,n))})},stop:function(t,i,s){var n=e.extend({},i,{item:s.element});s.cancelHelperRemoval=!1,e.each(s.sortables,function(){var e=this;e.isOver?(e.isOver=0,s.cancelHelperRemoval=!0,e.cancelHelperRemoval=!1,e._storedCSS={position:e.placeholder.css("position"),top:e.placeholder.css("top"),left:e.placeholder.css("left")},e._mouseStop(t),e.options.helper=e.options._helper):(e.cancelHelperRemoval=!0,e._trigger("deactivate",t,n))})},drag:function(t,i,s){e.each(s.sortables,function(){var n=!1,a=this;a.positionAbs=s.positionAbs,a.helperProportions=s.helperProportions,a.offset.click=s.offset.click,a._intersectsWith(a.containerCache)&&(n=!0,e.each(s.sortables,function(){return this.positionAbs=s.positionAbs,this.helperProportions=s.helperProportions,this.offset.click=s.offset.click,this!==a&&this._intersectsWith(this.containerCache)&&e.contains(a.element[0],this.element[0])&&(n=!1),n})),n?(a.isOver||(a.isOver=1,a.currentItem=i.helper.appendTo(a.element).data("ui-sortable-item",!0),a.options._helper=a.options.helper,a.options.helper=function(){return i.helper[0]},t.target=a.currentItem[0],a._mouseCapture(t,!0),a._mouseStart(t,!0,!0),a.offset.click.top=s.offset.click.top,a.offset.click.left=s.offset.click.left,a.offset.parent.left-=s.offset.parent.left-a.offset.parent.left,a.offset.parent.top-=s.offset.parent.top-a.offset.parent.top,s._trigger("toSortable",t),s.dropped=a.element,e.each(s.sortables,function(){this.refreshPositions()}),s.currentItem=s.element,a.fromOutside=s),a.currentItem&&(a._mouseDrag(t),i.position=a.position)):a.isOver&&(a.isOver=0,a.cancelHelperRemoval=!0,a.options._revert=a.options.revert,a.options.revert=!1,a._trigger("out",t,a._uiHash(a)),a._mouseStop(t,!0),a.options.revert=a.options._revert,a.options.helper=a.options._helper,a.placeholder&&a.placeholder.remove(),s._refreshOffsets(t),i.position=s._generatePosition(t,!0),s._trigger("fromSortable",t),s.dropped=!1,e.each(s.sortables,function(){this.refreshPositions()}))})}}),e.ui.plugin.add("draggable","cursor",{start:function(t,i,s){var n=e("body"),a=s.options;n.css("cursor")&&(a._cursor=n.css("cursor")),n.css("cursor",a.cursor)},stop:function(t,i,s){var n=s.options;n._cursor&&e("body").css("cursor",n._cursor)}}),e.ui.plugin.add("draggable","opacity",{start:function(t,i,s){var n=e(i.helper),a=s.options;n.css("opacity")&&(a._opacity=n.css("opacity")),n.css("opacity",a.opacity)},stop:function(t,i,s){var n=s.options;n._opacity&&e(i.helper).css("opacity",n._opacity)}}),e.ui.plugin.add("draggable","scroll",{start:function(e,t,i){i.scrollParentNotHidden||(i.scrollParentNotHidden=i.helper.scrollParent(!1)),i.scrollParentNotHidden[0]!==i.document[0]&&"HTML"!==i.scrollParentNotHidden[0].tagName&&(i.overflowOffset=i.scrollParentNotHidden.offset())},drag:function(t,i,s){var n=s.options,a=!1,o=s.scrollParentNotHidden[0],r=s.document[0];o!==r&&"HTML"!==o.tagName?(n.axis&&"x"===n.axis||(s.overflowOffset.top+o.offsetHeight-t.pageY=0;c--)h=s.snapElements[c].left-s.margins.left,l=h+s.snapElements[c].width,u=s.snapElements[c].top-s.margins.top,d=u+s.snapElements[c].height,h-m>v||g>l+m||u-m>b||y>d+m||!e.contains(s.snapElements[c].item.ownerDocument,s.snapElements[c].item)?(s.snapElements[c].snapping&&s.options.snap.release&&s.options.snap.release.call(s.element,t,e.extend(s._uiHash(),{snapItem:s.snapElements[c].item})),s.snapElements[c].snapping=!1):("inner"!==f.snapMode&&(n=m>=Math.abs(u-b),a=m>=Math.abs(d-y),o=m>=Math.abs(h-v),r=m>=Math.abs(l-g),n&&(i.position.top=s._convertPositionTo("relative",{top:u-s.helperProportions.height,left:0}).top),a&&(i.position.top=s._convertPositionTo("relative",{top:d,left:0}).top),o&&(i.position.left=s._convertPositionTo("relative",{top:0,left:h-s.helperProportions.width}).left),r&&(i.position.left=s._convertPositionTo("relative",{top:0,left:l}).left)),p=n||a||o||r,"outer"!==f.snapMode&&(n=m>=Math.abs(u-y),a=m>=Math.abs(d-b),o=m>=Math.abs(h-g),r=m>=Math.abs(l-v),n&&(i.position.top=s._convertPositionTo("relative",{top:u,left:0}).top),a&&(i.position.top=s._convertPositionTo("relative",{top:d-s.helperProportions.height,left:0}).top),o&&(i.position.left=s._convertPositionTo("relative",{top:0,left:h}).left),r&&(i.position.left=s._convertPositionTo("relative",{top:0,left:l-s.helperProportions.width}).left)),!s.snapElements[c].snapping&&(n||a||o||r||p)&&s.options.snap.snap&&s.options.snap.snap.call(s.element,t,e.extend(s._uiHash(),{snapItem:s.snapElements[c].item})),s.snapElements[c].snapping=n||a||o||r||p)}}),e.ui.plugin.add("draggable","stack",{start:function(t,i,s){var n,a=s.options,o=e.makeArray(e(a.stack)).sort(function(t,i){return(parseInt(e(t).css("zIndex"),10)||0)-(parseInt(e(i).css("zIndex"),10)||0)});o.length&&(n=parseInt(e(o[0]).css("zIndex"),10)||0,e(o).each(function(t){e(this).css("zIndex",n+t)}),this.css("zIndex",n+o.length))}}),e.ui.plugin.add("draggable","zIndex",{start:function(t,i,s){var n=e(i.helper),a=s.options;n.css("zIndex")&&(a._zIndex=n.css("zIndex")),n.css("zIndex",a.zIndex)},stop:function(t,i,s){var n=s.options;n._zIndex&&e(i.helper).css("zIndex",n._zIndex)}}),e.ui.draggable,e.widget("ui.droppable",{version:"1.11.2",widgetEventPrefix:"drop",options:{accept:"*",activeClass:!1,addClasses:!0,greedy:!1,hoverClass:!1,scope:"default",tolerance:"intersect",activate:null,deactivate:null,drop:null,out:null,over:null},_create:function(){var t,i=this.options,s=i.accept;this.isover=!1,this.isout=!0,this.accept=e.isFunction(s)?s:function(e){return e.is(s)},this.proportions=function(){return arguments.length?(t=arguments[0],void 0):t?t:t={width:this.element[0].offsetWidth,height:this.element[0].offsetHeight}},this._addToManager(i.scope),i.addClasses&&this.element.addClass("ui-droppable")},_addToManager:function(t){e.ui.ddmanager.droppables[t]=e.ui.ddmanager.droppables[t]||[],e.ui.ddmanager.droppables[t].push(this)},_splice:function(e){for(var t=0;e.length>t;t++)e[t]===this&&e.splice(t,1)},_destroy:function(){var t=e.ui.ddmanager.droppables[this.options.scope];this._splice(t),this.element.removeClass("ui-droppable ui-droppable-disabled")},_setOption:function(t,i){if("accept"===t)this.accept=e.isFunction(i)?i:function(e){return e.is(i)};else if("scope"===t){var s=e.ui.ddmanager.droppables[this.options.scope];this._splice(s),this._addToManager(i)}this._super(t,i)},_activate:function(t){var i=e.ui.ddmanager.current;this.options.activeClass&&this.element.addClass(this.options.activeClass),i&&this._trigger("activate",t,this.ui(i))},_deactivate:function(t){var i=e.ui.ddmanager.current;this.options.activeClass&&this.element.removeClass(this.options.activeClass),i&&this._trigger("deactivate",t,this.ui(i))},_over:function(t){var i=e.ui.ddmanager.current;i&&(i.currentItem||i.element)[0]!==this.element[0]&&this.accept.call(this.element[0],i.currentItem||i.element)&&(this.options.hoverClass&&this.element.addClass(this.options.hoverClass),this._trigger("over",t,this.ui(i)))},_out:function(t){var i=e.ui.ddmanager.current;i&&(i.currentItem||i.element)[0]!==this.element[0]&&this.accept.call(this.element[0],i.currentItem||i.element)&&(this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("out",t,this.ui(i)))},_drop:function(t,i){var s=i||e.ui.ddmanager.current,n=!1;return s&&(s.currentItem||s.element)[0]!==this.element[0]?(this.element.find(":data(ui-droppable)").not(".ui-draggable-dragging").each(function(){var i=e(this).droppable("instance");return i.options.greedy&&!i.options.disabled&&i.options.scope===s.options.scope&&i.accept.call(i.element[0],s.currentItem||s.element)&&e.ui.intersect(s,e.extend(i,{offset:i.element.offset()}),i.options.tolerance,t)?(n=!0,!1):void 0}),n?!1:this.accept.call(this.element[0],s.currentItem||s.element)?(this.options.activeClass&&this.element.removeClass(this.options.activeClass),this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("drop",t,this.ui(s)),this.element):!1):!1},ui:function(e){return{draggable:e.currentItem||e.element,helper:e.helper,position:e.position,offset:e.positionAbs}}}),e.ui.intersect=function(){function e(e,t,i){return e>=t&&t+i>e}return function(t,i,s,n){if(!i.offset)return!1;var a=(t.positionAbs||t.position.absolute).left+t.margins.left,o=(t.positionAbs||t.position.absolute).top+t.margins.top,r=a+t.helperProportions.width,h=o+t.helperProportions.height,l=i.offset.left,u=i.offset.top,d=l+i.proportions().width,c=u+i.proportions().height;switch(s){case"fit":return a>=l&&d>=r&&o>=u&&c>=h;case"intersect":return a+t.helperProportions.width/2>l&&d>r-t.helperProportions.width/2&&o+t.helperProportions.height/2>u&&c>h-t.helperProportions.height/2;case"pointer":return e(n.pageY,u,i.proportions().height)&&e(n.pageX,l,i.proportions().width);case"touch":return(o>=u&&c>=o||h>=u&&c>=h||u>o&&h>c)&&(a>=l&&d>=a||r>=l&&d>=r||l>a&&r>d);default:return!1}}}(),e.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(t,i){var s,n,a=e.ui.ddmanager.droppables[t.options.scope]||[],o=i?i.type:null,r=(t.currentItem||t.element).find(":data(ui-droppable)").addBack();e:for(s=0;a.length>s;s++)if(!(a[s].options.disabled||t&&!a[s].accept.call(a[s].element[0],t.currentItem||t.element))){for(n=0;r.length>n;n++)if(r[n]===a[s].element[0]){a[s].proportions().height=0;continue e}a[s].visible="none"!==a[s].element.css("display"),a[s].visible&&("mousedown"===o&&a[s]._activate.call(a[s],i),a[s].offset=a[s].element.offset(),a[s].proportions({width:a[s].element[0].offsetWidth,height:a[s].element[0].offsetHeight}))}},drop:function(t,i){var s=!1;return e.each((e.ui.ddmanager.droppables[t.options.scope]||[]).slice(),function(){this.options&&(!this.options.disabled&&this.visible&&e.ui.intersect(t,this,this.options.tolerance,i)&&(s=this._drop.call(this,i)||s),!this.options.disabled&&this.visible&&this.accept.call(this.element[0],t.currentItem||t.element)&&(this.isout=!0,this.isover=!1,this._deactivate.call(this,i)))}),s},dragStart:function(t,i){t.element.parentsUntil("body").bind("scroll.droppable",function(){t.options.refreshPositions||e.ui.ddmanager.prepareOffsets(t,i)})},drag:function(t,i){t.options.refreshPositions&&e.ui.ddmanager.prepareOffsets(t,i),e.each(e.ui.ddmanager.droppables[t.options.scope]||[],function(){if(!this.options.disabled&&!this.greedyChild&&this.visible){var s,n,a,o=e.ui.intersect(t,this,this.options.tolerance,i),r=!o&&this.isover?"isout":o&&!this.isover?"isover":null;r&&(this.options.greedy&&(n=this.options.scope,a=this.element.parents(":data(ui-droppable)").filter(function(){return e(this).droppable("instance").options.scope===n}),a.length&&(s=e(a[0]).droppable("instance"),s.greedyChild="isover"===r)),s&&"isover"===r&&(s.isover=!1,s.isout=!0,s._out.call(s,i)),this[r]=!0,this["isout"===r?"isover":"isout"]=!1,this["isover"===r?"_over":"_out"].call(this,i),s&&"isout"===r&&(s.isout=!1,s.isover=!0,s._over.call(s,i)))}})},dragStop:function(t,i){t.element.parentsUntil("body").unbind("scroll.droppable"),t.options.refreshPositions||e.ui.ddmanager.prepareOffsets(t,i)}},e.ui.droppable,e.widget("ui.resizable",e.ui.mouse,{version:"1.11.2",widgetEventPrefix:"resize",options:{alsoResize:!1,animate:!1,animateDuration:"slow",animateEasing:"swing",aspectRatio:!1,autoHide:!1,containment:!1,ghost:!1,grid:!1,handles:"e,s,se",helper:!1,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:90,resize:null,start:null,stop:null},_num:function(e){return parseInt(e,10)||0},_isNumber:function(e){return!isNaN(parseInt(e,10))},_hasScroll:function(t,i){if("hidden"===e(t).css("overflow"))return!1;var s=i&&"left"===i?"scrollLeft":"scrollTop",n=!1;return t[s]>0?!0:(t[s]=1,n=t[s]>0,t[s]=0,n)},_create:function(){var t,i,s,n,a,o=this,r=this.options;if(this.element.addClass("ui-resizable"),e.extend(this,{_aspectRatio:!!r.aspectRatio,aspectRatio:r.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:r.helper||r.ghost||r.animate?r.helper||"ui-resizable-helper":null}),this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)&&(this.element.wrap(e("
    ").css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("ui-resizable",this.element.resizable("instance")),this.elementIsWrapper=!0,this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")}),this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0}),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css({margin:this.originalElement.css("margin")}),this._proportionallyResize()),this.handles=r.handles||(e(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se"),this.handles.constructor===String)for("all"===this.handles&&(this.handles="n,e,s,w,se,sw,ne,nw"),t=this.handles.split(","),this.handles={},i=0;t.length>i;i++)s=e.trim(t[i]),a="ui-resizable-"+s,n=e("
    "),n.css({zIndex:r.zIndex}),"se"===s&&n.addClass("ui-icon ui-icon-gripsmall-diagonal-se"),this.handles[s]=".ui-resizable-"+s,this.element.append(n);this._renderAxis=function(t){var i,s,n,a;t=t||this.element;for(i in this.handles)this.handles[i].constructor===String&&(this.handles[i]=this.element.children(this.handles[i]).first().show()),this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)&&(s=e(this.handles[i],this.element),a=/sw|ne|nw|se|n|s/.test(i)?s.outerHeight():s.outerWidth(),n=["padding",/ne|nw|n/.test(i)?"Top":/se|sw|s/.test(i)?"Bottom":/^e$/.test(i)?"Right":"Left"].join(""),t.css(n,a),this._proportionallyResize()),e(this.handles[i]).length},this._renderAxis(this.element),this._handles=e(".ui-resizable-handle",this.element).disableSelection(),this._handles.mouseover(function(){o.resizing||(this.className&&(n=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)),o.axis=n&&n[1]?n[1]:"se")}),r.autoHide&&(this._handles.hide(),e(this.element).addClass("ui-resizable-autohide").mouseenter(function(){r.disabled||(e(this).removeClass("ui-resizable-autohide"),o._handles.show())}).mouseleave(function(){r.disabled||o.resizing||(e(this).addClass("ui-resizable-autohide"),o._handles.hide())})),this._mouseInit()},_destroy:function(){this._mouseDestroy();var t,i=function(t){e(t).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};return this.elementIsWrapper&&(i(this.element),t=this.element,this.originalElement.css({position:t.css("position"),width:t.outerWidth(),height:t.outerHeight(),top:t.css("top"),left:t.css("left")}).insertAfter(t),t.remove()),this.originalElement.css("resize",this.originalResizeStyle),i(this.originalElement),this},_mouseCapture:function(t){var i,s,n=!1;for(i in this.handles)s=e(this.handles[i])[0],(s===t.target||e.contains(s,t.target))&&(n=!0);return!this.options.disabled&&n},_mouseStart:function(t){var i,s,n,a=this.options,o=this.element;return this.resizing=!0,this._renderProxy(),i=this._num(this.helper.css("left")),s=this._num(this.helper.css("top")),a.containment&&(i+=e(a.containment).scrollLeft()||0,s+=e(a.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:i,top:s},this.size=this._helper?{width:this.helper.width(),height:this.helper.height()}:{width:o.width(),height:o.height()},this.originalSize=this._helper?{width:o.outerWidth(),height:o.outerHeight()}:{width:o.width(),height:o.height()},this.sizeDiff={width:o.outerWidth()-o.width(),height:o.outerHeight()-o.height()},this.originalPosition={left:i,top:s},this.originalMousePosition={left:t.pageX,top:t.pageY},this.aspectRatio="number"==typeof a.aspectRatio?a.aspectRatio:this.originalSize.width/this.originalSize.height||1,n=e(".ui-resizable-"+this.axis).css("cursor"),e("body").css("cursor","auto"===n?this.axis+"-resize":n),o.addClass("ui-resizable-resizing"),this._propagate("start",t),!0},_mouseDrag:function(t){var i,s,n=this.originalMousePosition,a=this.axis,o=t.pageX-n.left||0,r=t.pageY-n.top||0,h=this._change[a];return this._updatePrevProperties(),h?(i=h.apply(this,[t,o,r]),this._updateVirtualBoundaries(t.shiftKey),(this._aspectRatio||t.shiftKey)&&(i=this._updateRatio(i,t)),i=this._respectSize(i,t),this._updateCache(i),this._propagate("resize",t),s=this._applyChanges(),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),e.isEmptyObject(s)||(this._updatePrevProperties(),this._trigger("resize",t,this.ui()),this._applyChanges()),!1):!1},_mouseStop:function(t){this.resizing=!1;var i,s,n,a,o,r,h,l=this.options,u=this;return this._helper&&(i=this._proportionallyResizeElements,s=i.length&&/textarea/i.test(i[0].nodeName),n=s&&this._hasScroll(i[0],"left")?0:u.sizeDiff.height,a=s?0:u.sizeDiff.width,o={width:u.helper.width()-a,height:u.helper.height()-n},r=parseInt(u.element.css("left"),10)+(u.position.left-u.originalPosition.left)||null,h=parseInt(u.element.css("top"),10)+(u.position.top-u.originalPosition.top)||null,l.animate||this.element.css(e.extend(o,{top:h,left:r})),u.helper.height(u.size.height),u.helper.width(u.size.width),this._helper&&!l.animate&&this._proportionallyResize()),e("body").css("cursor","auto"),this.element.removeClass("ui-resizable-resizing"),this._propagate("stop",t),this._helper&&this.helper.remove(),!1},_updatePrevProperties:function(){this.prevPosition={top:this.position.top,left:this.position.left},this.prevSize={width:this.size.width,height:this.size.height}},_applyChanges:function(){var e={};return this.position.top!==this.prevPosition.top&&(e.top=this.position.top+"px"),this.position.left!==this.prevPosition.left&&(e.left=this.position.left+"px"),this.size.width!==this.prevSize.width&&(e.width=this.size.width+"px"),this.size.height!==this.prevSize.height&&(e.height=this.size.height+"px"),this.helper.css(e),e},_updateVirtualBoundaries:function(e){var t,i,s,n,a,o=this.options;a={minWidth:this._isNumber(o.minWidth)?o.minWidth:0,maxWidth:this._isNumber(o.maxWidth)?o.maxWidth:1/0,minHeight:this._isNumber(o.minHeight)?o.minHeight:0,maxHeight:this._isNumber(o.maxHeight)?o.maxHeight:1/0},(this._aspectRatio||e)&&(t=a.minHeight*this.aspectRatio,s=a.minWidth/this.aspectRatio,i=a.maxHeight*this.aspectRatio,n=a.maxWidth/this.aspectRatio,t>a.minWidth&&(a.minWidth=t),s>a.minHeight&&(a.minHeight=s),a.maxWidth>i&&(a.maxWidth=i),a.maxHeight>n&&(a.maxHeight=n)),this._vBoundaries=a},_updateCache:function(e){this.offset=this.helper.offset(),this._isNumber(e.left)&&(this.position.left=e.left),this._isNumber(e.top)&&(this.position.top=e.top),this._isNumber(e.height)&&(this.size.height=e.height),this._isNumber(e.width)&&(this.size.width=e.width)},_updateRatio:function(e){var t=this.position,i=this.size,s=this.axis;return this._isNumber(e.height)?e.width=e.height*this.aspectRatio:this._isNumber(e.width)&&(e.height=e.width/this.aspectRatio),"sw"===s&&(e.left=t.left+(i.width-e.width),e.top=null),"nw"===s&&(e.top=t.top+(i.height-e.height),e.left=t.left+(i.width-e.width)),e},_respectSize:function(e){var t=this._vBoundaries,i=this.axis,s=this._isNumber(e.width)&&t.maxWidth&&t.maxWidthe.width,o=this._isNumber(e.height)&&t.minHeight&&t.minHeight>e.height,r=this.originalPosition.left+this.originalSize.width,h=this.position.top+this.size.height,l=/sw|nw|w/.test(i),u=/nw|ne|n/.test(i);return a&&(e.width=t.minWidth),o&&(e.height=t.minHeight),s&&(e.width=t.maxWidth),n&&(e.height=t.maxHeight),a&&l&&(e.left=r-t.minWidth),s&&l&&(e.left=r-t.maxWidth),o&&u&&(e.top=h-t.minHeight),n&&u&&(e.top=h-t.maxHeight),e.width||e.height||e.left||!e.top?e.width||e.height||e.top||!e.left||(e.left=null):e.top=null,e},_getPaddingPlusBorderDimensions:function(e){for(var t=0,i=[],s=[e.css("borderTopWidth"),e.css("borderRightWidth"),e.css("borderBottomWidth"),e.css("borderLeftWidth")],n=[e.css("paddingTop"),e.css("paddingRight"),e.css("paddingBottom"),e.css("paddingLeft")];4>t;t++)i[t]=parseInt(s[t],10)||0,i[t]+=parseInt(n[t],10)||0;return{height:i[0]+i[2],width:i[1]+i[3]}},_proportionallyResize:function(){if(this._proportionallyResizeElements.length)for(var e,t=0,i=this.helper||this.element;this._proportionallyResizeElements.length>t;t++)e=this._proportionallyResizeElements[t],this.outerDimensions||(this.outerDimensions=this._getPaddingPlusBorderDimensions(e)),e.css({height:i.height()-this.outerDimensions.height||0,width:i.width()-this.outerDimensions.width||0})},_renderProxy:function(){var t=this.element,i=this.options;this.elementOffset=t.offset(),this._helper?(this.helper=this.helper||e("
    "),this.helper.addClass(this._helper).css({width:this.element.outerWidth()-1,height:this.element.outerHeight()-1,position:"absolute",left:this.elementOffset.left+"px",top:this.elementOffset.top+"px",zIndex:++i.zIndex}),this.helper.appendTo("body").disableSelection()):this.helper=this.element},_change:{e:function(e,t){return{width:this.originalSize.width+t}},w:function(e,t){var i=this.originalSize,s=this.originalPosition;return{left:s.left+t,width:i.width-t}},n:function(e,t,i){var s=this.originalSize,n=this.originalPosition;return{top:n.top+i,height:s.height-i}},s:function(e,t,i){return{height:this.originalSize.height+i}},se:function(t,i,s){return e.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[t,i,s]))},sw:function(t,i,s){return e.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[t,i,s]))},ne:function(t,i,s){return e.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[t,i,s]))},nw:function(t,i,s){return e.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[t,i,s]))}},_propagate:function(t,i){e.ui.plugin.call(this,t,[i,this.ui()]),"resize"!==t&&this._trigger(t,i,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),e.ui.plugin.add("resizable","animate",{stop:function(t){var i=e(this).resizable("instance"),s=i.options,n=i._proportionallyResizeElements,a=n.length&&/textarea/i.test(n[0].nodeName),o=a&&i._hasScroll(n[0],"left")?0:i.sizeDiff.height,r=a?0:i.sizeDiff.width,h={width:i.size.width-r,height:i.size.height-o},l=parseInt(i.element.css("left"),10)+(i.position.left-i.originalPosition.left)||null,u=parseInt(i.element.css("top"),10)+(i.position.top-i.originalPosition.top)||null;i.element.animate(e.extend(h,u&&l?{top:u,left:l}:{}),{duration:s.animateDuration,easing:s.animateEasing,step:function(){var s={width:parseInt(i.element.css("width"),10),height:parseInt(i.element.css("height"),10),top:parseInt(i.element.css("top"),10),left:parseInt(i.element.css("left"),10)};n&&n.length&&e(n[0]).css({width:s.width,height:s.height}),i._updateCache(s),i._propagate("resize",t)}})}}),e.ui.plugin.add("resizable","containment",{start:function(){var t,i,s,n,a,o,r,h=e(this).resizable("instance"),l=h.options,u=h.element,d=l.containment,c=d instanceof e?d.get(0):/parent/.test(d)?u.parent().get(0):d;c&&(h.containerElement=e(c),/document/.test(d)||d===document?(h.containerOffset={left:0,top:0},h.containerPosition={left:0,top:0},h.parentData={element:e(document),left:0,top:0,width:e(document).width(),height:e(document).height()||document.body.parentNode.scrollHeight}):(t=e(c),i=[],e(["Top","Right","Left","Bottom"]).each(function(e,s){i[e]=h._num(t.css("padding"+s))}),h.containerOffset=t.offset(),h.containerPosition=t.position(),h.containerSize={height:t.innerHeight()-i[3],width:t.innerWidth()-i[1]},s=h.containerOffset,n=h.containerSize.height,a=h.containerSize.width,o=h._hasScroll(c,"left")?c.scrollWidth:a,r=h._hasScroll(c)?c.scrollHeight:n,h.parentData={element:c,left:s.left,top:s.top,width:o,height:r}))},resize:function(t){var i,s,n,a,o=e(this).resizable("instance"),r=o.options,h=o.containerOffset,l=o.position,u=o._aspectRatio||t.shiftKey,d={top:0,left:0},c=o.containerElement,p=!0;c[0]!==document&&/static/.test(c.css("position"))&&(d=h),l.left<(o._helper?h.left:0)&&(o.size.width=o.size.width+(o._helper?o.position.left-h.left:o.position.left-d.left),u&&(o.size.height=o.size.width/o.aspectRatio,p=!1),o.position.left=r.helper?h.left:0),l.top<(o._helper?h.top:0)&&(o.size.height=o.size.height+(o._helper?o.position.top-h.top:o.position.top),u&&(o.size.width=o.size.height*o.aspectRatio,p=!1),o.position.top=o._helper?h.top:0),n=o.containerElement.get(0)===o.element.parent().get(0),a=/relative|absolute/.test(o.containerElement.css("position")),n&&a?(o.offset.left=o.parentData.left+o.position.left,o.offset.top=o.parentData.top+o.position.top):(o.offset.left=o.element.offset().left,o.offset.top=o.element.offset().top),i=Math.abs(o.sizeDiff.width+(o._helper?o.offset.left-d.left:o.offset.left-h.left)),s=Math.abs(o.sizeDiff.height+(o._helper?o.offset.top-d.top:o.offset.top-h.top)),i+o.size.width>=o.parentData.width&&(o.size.width=o.parentData.width-i,u&&(o.size.height=o.size.width/o.aspectRatio,p=!1)),s+o.size.height>=o.parentData.height&&(o.size.height=o.parentData.height-s,u&&(o.size.width=o.size.height*o.aspectRatio,p=!1)),p||(o.position.left=o.prevPosition.left,o.position.top=o.prevPosition.top,o.size.width=o.prevSize.width,o.size.height=o.prevSize.height)},stop:function(){var t=e(this).resizable("instance"),i=t.options,s=t.containerOffset,n=t.containerPosition,a=t.containerElement,o=e(t.helper),r=o.offset(),h=o.outerWidth()-t.sizeDiff.width,l=o.outerHeight()-t.sizeDiff.height;t._helper&&!i.animate&&/relative/.test(a.css("position"))&&e(this).css({left:r.left-n.left-s.left,width:h,height:l}),t._helper&&!i.animate&&/static/.test(a.css("position"))&&e(this).css({left:r.left-n.left-s.left,width:h,height:l})}}),e.ui.plugin.add("resizable","alsoResize",{start:function(){var t=e(this).resizable("instance"),i=t.options,s=function(t){e(t).each(function(){var t=e(this);t.data("ui-resizable-alsoresize",{width:parseInt(t.width(),10),height:parseInt(t.height(),10),left:parseInt(t.css("left"),10),top:parseInt(t.css("top"),10)})})};"object"!=typeof i.alsoResize||i.alsoResize.parentNode?s(i.alsoResize):i.alsoResize.length?(i.alsoResize=i.alsoResize[0],s(i.alsoResize)):e.each(i.alsoResize,function(e){s(e)})},resize:function(t,i){var s=e(this).resizable("instance"),n=s.options,a=s.originalSize,o=s.originalPosition,r={height:s.size.height-a.height||0,width:s.size.width-a.width||0,top:s.position.top-o.top||0,left:s.position.left-o.left||0},h=function(t,s){e(t).each(function(){var t=e(this),n=e(this).data("ui-resizable-alsoresize"),a={},o=s&&s.length?s:t.parents(i.originalElement[0]).length?["width","height"]:["width","height","top","left"];e.each(o,function(e,t){var i=(n[t]||0)+(r[t]||0);i&&i>=0&&(a[t]=i||null)}),t.css(a)})};"object"!=typeof n.alsoResize||n.alsoResize.nodeType?h(n.alsoResize):e.each(n.alsoResize,function(e,t){h(e,t)})},stop:function(){e(this).removeData("resizable-alsoresize")}}),e.ui.plugin.add("resizable","ghost",{start:function(){var t=e(this).resizable("instance"),i=t.options,s=t.size;t.ghost=t.originalElement.clone(),t.ghost.css({opacity:.25,display:"block",position:"relative",height:s.height,width:s.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass("string"==typeof i.ghost?i.ghost:""),t.ghost.appendTo(t.helper)},resize:function(){var t=e(this).resizable("instance");t.ghost&&t.ghost.css({position:"relative",height:t.size.height,width:t.size.width})},stop:function(){var t=e(this).resizable("instance");t.ghost&&t.helper&&t.helper.get(0).removeChild(t.ghost.get(0))}}),e.ui.plugin.add("resizable","grid",{resize:function(){var t,i=e(this).resizable("instance"),s=i.options,n=i.size,a=i.originalSize,o=i.originalPosition,r=i.axis,h="number"==typeof s.grid?[s.grid,s.grid]:s.grid,l=h[0]||1,u=h[1]||1,d=Math.round((n.width-a.width)/l)*l,c=Math.round((n.height-a.height)/u)*u,p=a.width+d,f=a.height+c,m=s.maxWidth&&p>s.maxWidth,g=s.maxHeight&&f>s.maxHeight,v=s.minWidth&&s.minWidth>p,y=s.minHeight&&s.minHeight>f;s.grid=h,v&&(p+=l),y&&(f+=u),m&&(p-=l),g&&(f-=u),/^(se|s|e)$/.test(r)?(i.size.width=p,i.size.height=f):/^(ne)$/.test(r)?(i.size.width=p,i.size.height=f,i.position.top=o.top-c):/^(sw)$/.test(r)?(i.size.width=p,i.size.height=f,i.position.left=o.left-d):((0>=f-u||0>=p-l)&&(t=i._getPaddingPlusBorderDimensions(this)),f-u>0?(i.size.height=f,i.position.top=o.top-c):(f=u-t.height,i.size.height=f,i.position.top=o.top+a.height-f),p-l>0?(i.size.width=p,i.position.left=o.left-d):(p=u-t.height,i.size.width=p,i.position.left=o.left+a.width-p))}}),e.ui.resizable,e.widget("ui.selectable",e.ui.mouse,{version:"1.11.2",options:{appendTo:"body",autoRefresh:!0,distance:0,filter:"*",tolerance:"touch",selected:null,selecting:null,start:null,stop:null,unselected:null,unselecting:null},_create:function(){var t,i=this; +this.element.addClass("ui-selectable"),this.dragged=!1,this.refresh=function(){t=e(i.options.filter,i.element[0]),t.addClass("ui-selectee"),t.each(function(){var t=e(this),i=t.offset();e.data(this,"selectable-item",{element:this,$element:t,left:i.left,top:i.top,right:i.left+t.outerWidth(),bottom:i.top+t.outerHeight(),startselected:!1,selected:t.hasClass("ui-selected"),selecting:t.hasClass("ui-selecting"),unselecting:t.hasClass("ui-unselecting")})})},this.refresh(),this.selectees=t.addClass("ui-selectee"),this._mouseInit(),this.helper=e("
    ")},_destroy:function(){this.selectees.removeClass("ui-selectee").removeData("selectable-item"),this.element.removeClass("ui-selectable ui-selectable-disabled"),this._mouseDestroy()},_mouseStart:function(t){var i=this,s=this.options;this.opos=[t.pageX,t.pageY],this.options.disabled||(this.selectees=e(s.filter,this.element[0]),this._trigger("start",t),e(s.appendTo).append(this.helper),this.helper.css({left:t.pageX,top:t.pageY,width:0,height:0}),s.autoRefresh&&this.refresh(),this.selectees.filter(".ui-selected").each(function(){var s=e.data(this,"selectable-item");s.startselected=!0,t.metaKey||t.ctrlKey||(s.$element.removeClass("ui-selected"),s.selected=!1,s.$element.addClass("ui-unselecting"),s.unselecting=!0,i._trigger("unselecting",t,{unselecting:s.element}))}),e(t.target).parents().addBack().each(function(){var s,n=e.data(this,"selectable-item");return n?(s=!t.metaKey&&!t.ctrlKey||!n.$element.hasClass("ui-selected"),n.$element.removeClass(s?"ui-unselecting":"ui-selected").addClass(s?"ui-selecting":"ui-unselecting"),n.unselecting=!s,n.selecting=s,n.selected=s,s?i._trigger("selecting",t,{selecting:n.element}):i._trigger("unselecting",t,{unselecting:n.element}),!1):void 0}))},_mouseDrag:function(t){if(this.dragged=!0,!this.options.disabled){var i,s=this,n=this.options,a=this.opos[0],o=this.opos[1],r=t.pageX,h=t.pageY;return a>r&&(i=r,r=a,a=i),o>h&&(i=h,h=o,o=i),this.helper.css({left:a,top:o,width:r-a,height:h-o}),this.selectees.each(function(){var i=e.data(this,"selectable-item"),l=!1;i&&i.element!==s.element[0]&&("touch"===n.tolerance?l=!(i.left>r||a>i.right||i.top>h||o>i.bottom):"fit"===n.tolerance&&(l=i.left>a&&r>i.right&&i.top>o&&h>i.bottom),l?(i.selected&&(i.$element.removeClass("ui-selected"),i.selected=!1),i.unselecting&&(i.$element.removeClass("ui-unselecting"),i.unselecting=!1),i.selecting||(i.$element.addClass("ui-selecting"),i.selecting=!0,s._trigger("selecting",t,{selecting:i.element}))):(i.selecting&&((t.metaKey||t.ctrlKey)&&i.startselected?(i.$element.removeClass("ui-selecting"),i.selecting=!1,i.$element.addClass("ui-selected"),i.selected=!0):(i.$element.removeClass("ui-selecting"),i.selecting=!1,i.startselected&&(i.$element.addClass("ui-unselecting"),i.unselecting=!0),s._trigger("unselecting",t,{unselecting:i.element}))),i.selected&&(t.metaKey||t.ctrlKey||i.startselected||(i.$element.removeClass("ui-selected"),i.selected=!1,i.$element.addClass("ui-unselecting"),i.unselecting=!0,s._trigger("unselecting",t,{unselecting:i.element})))))}),!1}},_mouseStop:function(t){var i=this;return this.dragged=!1,e(".ui-unselecting",this.element[0]).each(function(){var s=e.data(this,"selectable-item");s.$element.removeClass("ui-unselecting"),s.unselecting=!1,s.startselected=!1,i._trigger("unselected",t,{unselected:s.element})}),e(".ui-selecting",this.element[0]).each(function(){var s=e.data(this,"selectable-item");s.$element.removeClass("ui-selecting").addClass("ui-selected"),s.selecting=!1,s.selected=!0,s.startselected=!0,i._trigger("selected",t,{selected:s.element})}),this._trigger("stop",t),this.helper.remove(),!1}}),e.widget("ui.sortable",e.ui.mouse,{version:"1.11.2",widgetEventPrefix:"sort",ready:!1,options:{appendTo:"parent",axis:!1,connectWith:!1,containment:!1,cursor:"auto",cursorAt:!1,dropOnEmpty:!0,forcePlaceholderSize:!1,forceHelperSize:!1,grid:!1,handle:!1,helper:"original",items:"> *",opacity:!1,placeholder:!1,revert:!1,scroll:!0,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1e3,activate:null,beforeStop:null,change:null,deactivate:null,out:null,over:null,receive:null,remove:null,sort:null,start:null,stop:null,update:null},_isOverAxis:function(e,t,i){return e>=t&&t+i>e},_isFloating:function(e){return/left|right/.test(e.css("float"))||/inline|table-cell/.test(e.css("display"))},_create:function(){var e=this.options;this.containerCache={},this.element.addClass("ui-sortable"),this.refresh(),this.floating=this.items.length?"x"===e.axis||this._isFloating(this.items[0].item):!1,this.offset=this.element.offset(),this._mouseInit(),this._setHandleClassName(),this.ready=!0},_setOption:function(e,t){this._super(e,t),"handle"===e&&this._setHandleClassName()},_setHandleClassName:function(){this.element.find(".ui-sortable-handle").removeClass("ui-sortable-handle"),e.each(this.items,function(){(this.instance.options.handle?this.item.find(this.instance.options.handle):this.item).addClass("ui-sortable-handle")})},_destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled").find(".ui-sortable-handle").removeClass("ui-sortable-handle"),this._mouseDestroy();for(var e=this.items.length-1;e>=0;e--)this.items[e].item.removeData(this.widgetName+"-item");return this},_mouseCapture:function(t,i){var s=null,n=!1,a=this;return this.reverting?!1:this.options.disabled||"static"===this.options.type?!1:(this._refreshItems(t),e(t.target).parents().each(function(){return e.data(this,a.widgetName+"-item")===a?(s=e(this),!1):void 0}),e.data(t.target,a.widgetName+"-item")===a&&(s=e(t.target)),s?!this.options.handle||i||(e(this.options.handle,s).find("*").addBack().each(function(){this===t.target&&(n=!0)}),n)?(this.currentItem=s,this._removeCurrentsFromItems(),!0):!1:!1)},_mouseStart:function(t,i,s){var n,a,o=this.options;if(this.currentContainer=this,this.refreshPositions(),this.helper=this._createHelper(t),this._cacheHelperProportions(),this._cacheMargins(),this.scrollParent=this.helper.scrollParent(),this.offset=this.currentItem.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},e.extend(this.offset,{click:{left:t.pageX-this.offset.left,top:t.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.helper.css("position","absolute"),this.cssPosition=this.helper.css("position"),this.originalPosition=this._generatePosition(t),this.originalPageX=t.pageX,this.originalPageY=t.pageY,o.cursorAt&&this._adjustOffsetFromHelper(o.cursorAt),this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]},this.helper[0]!==this.currentItem[0]&&this.currentItem.hide(),this._createPlaceholder(),o.containment&&this._setContainment(),o.cursor&&"auto"!==o.cursor&&(a=this.document.find("body"),this.storedCursor=a.css("cursor"),a.css("cursor",o.cursor),this.storedStylesheet=e("").appendTo(a)),o.opacity&&(this.helper.css("opacity")&&(this._storedOpacity=this.helper.css("opacity")),this.helper.css("opacity",o.opacity)),o.zIndex&&(this.helper.css("zIndex")&&(this._storedZIndex=this.helper.css("zIndex")),this.helper.css("zIndex",o.zIndex)),this.scrollParent[0]!==document&&"HTML"!==this.scrollParent[0].tagName&&(this.overflowOffset=this.scrollParent.offset()),this._trigger("start",t,this._uiHash()),this._preserveHelperProportions||this._cacheHelperProportions(),!s)for(n=this.containers.length-1;n>=0;n--)this.containers[n]._trigger("activate",t,this._uiHash(this));return e.ui.ddmanager&&(e.ui.ddmanager.current=this),e.ui.ddmanager&&!o.dropBehaviour&&e.ui.ddmanager.prepareOffsets(this,t),this.dragging=!0,this.helper.addClass("ui-sortable-helper"),this._mouseDrag(t),!0},_mouseDrag:function(t){var i,s,n,a,o=this.options,r=!1;for(this.position=this._generatePosition(t),this.positionAbs=this._convertPositionTo("absolute"),this.lastPositionAbs||(this.lastPositionAbs=this.positionAbs),this.options.scroll&&(this.scrollParent[0]!==document&&"HTML"!==this.scrollParent[0].tagName?(this.overflowOffset.top+this.scrollParent[0].offsetHeight-t.pageY=0;i--)if(s=this.items[i],n=s.item[0],a=this._intersectsWithPointer(s),a&&s.instance===this.currentContainer&&n!==this.currentItem[0]&&this.placeholder[1===a?"next":"prev"]()[0]!==n&&!e.contains(this.placeholder[0],n)&&("semi-dynamic"===this.options.type?!e.contains(this.element[0],n):!0)){if(this.direction=1===a?"down":"up","pointer"!==this.options.tolerance&&!this._intersectsWithSides(s))break;this._rearrange(t,s),this._trigger("change",t,this._uiHash());break}return this._contactContainers(t),e.ui.ddmanager&&e.ui.ddmanager.drag(this,t),this._trigger("sort",t,this._uiHash()),this.lastPositionAbs=this.positionAbs,!1},_mouseStop:function(t,i){if(t){if(e.ui.ddmanager&&!this.options.dropBehaviour&&e.ui.ddmanager.drop(this,t),this.options.revert){var s=this,n=this.placeholder.offset(),a=this.options.axis,o={};a&&"x"!==a||(o.left=n.left-this.offset.parent.left-this.margins.left+(this.offsetParent[0]===document.body?0:this.offsetParent[0].scrollLeft)),a&&"y"!==a||(o.top=n.top-this.offset.parent.top-this.margins.top+(this.offsetParent[0]===document.body?0:this.offsetParent[0].scrollTop)),this.reverting=!0,e(this.helper).animate(o,parseInt(this.options.revert,10)||500,function(){s._clear(t)})}else this._clear(t,i);return!1}},cancel:function(){if(this.dragging){this._mouseUp({target:null}),"original"===this.options.helper?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"):this.currentItem.show();for(var t=this.containers.length-1;t>=0;t--)this.containers[t]._trigger("deactivate",null,this._uiHash(this)),this.containers[t].containerCache.over&&(this.containers[t]._trigger("out",null,this._uiHash(this)),this.containers[t].containerCache.over=0)}return this.placeholder&&(this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]),"original"!==this.options.helper&&this.helper&&this.helper[0].parentNode&&this.helper.remove(),e.extend(this,{helper:null,dragging:!1,reverting:!1,_noFinalSort:null}),this.domPosition.prev?e(this.domPosition.prev).after(this.currentItem):e(this.domPosition.parent).prepend(this.currentItem)),this},serialize:function(t){var i=this._getItemsAsjQuery(t&&t.connected),s=[];return t=t||{},e(i).each(function(){var i=(e(t.item||this).attr(t.attribute||"id")||"").match(t.expression||/(.+)[\-=_](.+)/);i&&s.push((t.key||i[1]+"[]")+"="+(t.key&&t.expression?i[1]:i[2]))}),!s.length&&t.key&&s.push(t.key+"="),s.join("&")},toArray:function(t){var i=this._getItemsAsjQuery(t&&t.connected),s=[];return t=t||{},i.each(function(){s.push(e(t.item||this).attr(t.attribute||"id")||"")}),s},_intersectsWith:function(e){var t=this.positionAbs.left,i=t+this.helperProportions.width,s=this.positionAbs.top,n=s+this.helperProportions.height,a=e.left,o=a+e.width,r=e.top,h=r+e.height,l=this.offset.click.top,u=this.offset.click.left,d="x"===this.options.axis||s+l>r&&h>s+l,c="y"===this.options.axis||t+u>a&&o>t+u,p=d&&c;return"pointer"===this.options.tolerance||this.options.forcePointerForContainers||"pointer"!==this.options.tolerance&&this.helperProportions[this.floating?"width":"height"]>e[this.floating?"width":"height"]?p:t+this.helperProportions.width/2>a&&o>i-this.helperProportions.width/2&&s+this.helperProportions.height/2>r&&h>n-this.helperProportions.height/2},_intersectsWithPointer:function(e){var t="x"===this.options.axis||this._isOverAxis(this.positionAbs.top+this.offset.click.top,e.top,e.height),i="y"===this.options.axis||this._isOverAxis(this.positionAbs.left+this.offset.click.left,e.left,e.width),s=t&&i,n=this._getDragVerticalDirection(),a=this._getDragHorizontalDirection();return s?this.floating?a&&"right"===a||"down"===n?2:1:n&&("down"===n?2:1):!1},_intersectsWithSides:function(e){var t=this._isOverAxis(this.positionAbs.top+this.offset.click.top,e.top+e.height/2,e.height),i=this._isOverAxis(this.positionAbs.left+this.offset.click.left,e.left+e.width/2,e.width),s=this._getDragVerticalDirection(),n=this._getDragHorizontalDirection();return this.floating&&n?"right"===n&&i||"left"===n&&!i:s&&("down"===s&&t||"up"===s&&!t)},_getDragVerticalDirection:function(){var e=this.positionAbs.top-this.lastPositionAbs.top;return 0!==e&&(e>0?"down":"up")},_getDragHorizontalDirection:function(){var e=this.positionAbs.left-this.lastPositionAbs.left;return 0!==e&&(e>0?"right":"left")},refresh:function(e){return this._refreshItems(e),this._setHandleClassName(),this.refreshPositions(),this},_connectWith:function(){var e=this.options;return e.connectWith.constructor===String?[e.connectWith]:e.connectWith},_getItemsAsjQuery:function(t){function i(){r.push(this)}var s,n,a,o,r=[],h=[],l=this._connectWith();if(l&&t)for(s=l.length-1;s>=0;s--)for(a=e(l[s]),n=a.length-1;n>=0;n--)o=e.data(a[n],this.widgetFullName),o&&o!==this&&!o.options.disabled&&h.push([e.isFunction(o.options.items)?o.options.items.call(o.element):e(o.options.items,o.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),o]);for(h.push([e.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):e(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]),s=h.length-1;s>=0;s--)h[s][0].each(i);return e(r)},_removeCurrentsFromItems:function(){var t=this.currentItem.find(":data("+this.widgetName+"-item)");this.items=e.grep(this.items,function(e){for(var i=0;t.length>i;i++)if(t[i]===e.item[0])return!1;return!0})},_refreshItems:function(t){this.items=[],this.containers=[this];var i,s,n,a,o,r,h,l,u=this.items,d=[[e.isFunction(this.options.items)?this.options.items.call(this.element[0],t,{item:this.currentItem}):e(this.options.items,this.element),this]],c=this._connectWith();if(c&&this.ready)for(i=c.length-1;i>=0;i--)for(n=e(c[i]),s=n.length-1;s>=0;s--)a=e.data(n[s],this.widgetFullName),a&&a!==this&&!a.options.disabled&&(d.push([e.isFunction(a.options.items)?a.options.items.call(a.element[0],t,{item:this.currentItem}):e(a.options.items,a.element),a]),this.containers.push(a));for(i=d.length-1;i>=0;i--)for(o=d[i][1],r=d[i][0],s=0,l=r.length;l>s;s++)h=e(r[s]),h.data(this.widgetName+"-item",o),u.push({item:h,instance:o,width:0,height:0,left:0,top:0})},refreshPositions:function(t){this.offsetParent&&this.helper&&(this.offset.parent=this._getParentOffset());var i,s,n,a;for(i=this.items.length-1;i>=0;i--)s=this.items[i],s.instance!==this.currentContainer&&this.currentContainer&&s.item[0]!==this.currentItem[0]||(n=this.options.toleranceElement?e(this.options.toleranceElement,s.item):s.item,t||(s.width=n.outerWidth(),s.height=n.outerHeight()),a=n.offset(),s.left=a.left,s.top=a.top);if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(i=this.containers.length-1;i>=0;i--)a=this.containers[i].element.offset(),this.containers[i].containerCache.left=a.left,this.containers[i].containerCache.top=a.top,this.containers[i].containerCache.width=this.containers[i].element.outerWidth(),this.containers[i].containerCache.height=this.containers[i].element.outerHeight();return this},_createPlaceholder:function(t){t=t||this;var i,s=t.options;s.placeholder&&s.placeholder.constructor!==String||(i=s.placeholder,s.placeholder={element:function(){var s=t.currentItem[0].nodeName.toLowerCase(),n=e("<"+s+">",t.document[0]).addClass(i||t.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper");return"tr"===s?t.currentItem.children().each(function(){e(" ",t.document[0]).attr("colspan",e(this).attr("colspan")||1).appendTo(n)}):"img"===s&&n.attr("src",t.currentItem.attr("src")),i||n.css("visibility","hidden"),n},update:function(e,n){(!i||s.forcePlaceholderSize)&&(n.height()||n.height(t.currentItem.innerHeight()-parseInt(t.currentItem.css("paddingTop")||0,10)-parseInt(t.currentItem.css("paddingBottom")||0,10)),n.width()||n.width(t.currentItem.innerWidth()-parseInt(t.currentItem.css("paddingLeft")||0,10)-parseInt(t.currentItem.css("paddingRight")||0,10)))}}),t.placeholder=e(s.placeholder.element.call(t.element,t.currentItem)),t.currentItem.after(t.placeholder),s.placeholder.update(t,t.placeholder)},_contactContainers:function(t){var i,s,n,a,o,r,h,l,u,d,c=null,p=null;for(i=this.containers.length-1;i>=0;i--)if(!e.contains(this.currentItem[0],this.containers[i].element[0]))if(this._intersectsWith(this.containers[i].containerCache)){if(c&&e.contains(this.containers[i].element[0],c.element[0]))continue;c=this.containers[i],p=i}else this.containers[i].containerCache.over&&(this.containers[i]._trigger("out",t,this._uiHash(this)),this.containers[i].containerCache.over=0);if(c)if(1===this.containers.length)this.containers[p].containerCache.over||(this.containers[p]._trigger("over",t,this._uiHash(this)),this.containers[p].containerCache.over=1);else{for(n=1e4,a=null,u=c.floating||this._isFloating(this.currentItem),o=u?"left":"top",r=u?"width":"height",d=u?"clientX":"clientY",s=this.items.length-1;s>=0;s--)e.contains(this.containers[p].element[0],this.items[s].item[0])&&this.items[s].item[0]!==this.currentItem[0]&&(h=this.items[s].item.offset()[o],l=!1,t[d]-h>this.items[s][r]/2&&(l=!0),n>Math.abs(t[d]-h)&&(n=Math.abs(t[d]-h),a=this.items[s],this.direction=l?"up":"down"));if(!a&&!this.options.dropOnEmpty)return;if(this.currentContainer===this.containers[p])return this.currentContainer.containerCache.over||(this.containers[p]._trigger("over",t,this._uiHash()),this.currentContainer.containerCache.over=1),void 0;a?this._rearrange(t,a,null,!0):this._rearrange(t,null,this.containers[p].element,!0),this._trigger("change",t,this._uiHash()),this.containers[p]._trigger("change",t,this._uiHash(this)),this.currentContainer=this.containers[p],this.options.placeholder.update(this.currentContainer,this.placeholder),this.containers[p]._trigger("over",t,this._uiHash(this)),this.containers[p].containerCache.over=1}},_createHelper:function(t){var i=this.options,s=e.isFunction(i.helper)?e(i.helper.apply(this.element[0],[t,this.currentItem])):"clone"===i.helper?this.currentItem.clone():this.currentItem;return s.parents("body").length||e("parent"!==i.appendTo?i.appendTo:this.currentItem[0].parentNode)[0].appendChild(s[0]),s[0]===this.currentItem[0]&&(this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css("position"),top:this.currentItem.css("top"),left:this.currentItem.css("left")}),(!s[0].style.width||i.forceHelperSize)&&s.width(this.currentItem.width()),(!s[0].style.height||i.forceHelperSize)&&s.height(this.currentItem.height()),s},_adjustOffsetFromHelper:function(t){"string"==typeof t&&(t=t.split(" ")),e.isArray(t)&&(t={left:+t[0],top:+t[1]||0}),"left"in t&&(this.offset.click.left=t.left+this.margins.left),"right"in t&&(this.offset.click.left=this.helperProportions.width-t.right+this.margins.left),"top"in t&&(this.offset.click.top=t.top+this.margins.top),"bottom"in t&&(this.offset.click.top=this.helperProportions.height-t.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var t=this.offsetParent.offset();return"absolute"===this.cssPosition&&this.scrollParent[0]!==document&&e.contains(this.scrollParent[0],this.offsetParent[0])&&(t.left+=this.scrollParent.scrollLeft(),t.top+=this.scrollParent.scrollTop()),(this.offsetParent[0]===document.body||this.offsetParent[0].tagName&&"html"===this.offsetParent[0].tagName.toLowerCase()&&e.ui.ie)&&(t={top:0,left:0}),{top:t.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:t.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if("relative"===this.cssPosition){var e=this.currentItem.position();return{top:e.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:e.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.currentItem.css("marginLeft"),10)||0,top:parseInt(this.currentItem.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var t,i,s,n=this.options;"parent"===n.containment&&(n.containment=this.helper[0].parentNode),("document"===n.containment||"window"===n.containment)&&(this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,e("document"===n.containment?document:window).width()-this.helperProportions.width-this.margins.left,(e("document"===n.containment?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top]),/^(document|window|parent)$/.test(n.containment)||(t=e(n.containment)[0],i=e(n.containment).offset(),s="hidden"!==e(t).css("overflow"),this.containment=[i.left+(parseInt(e(t).css("borderLeftWidth"),10)||0)+(parseInt(e(t).css("paddingLeft"),10)||0)-this.margins.left,i.top+(parseInt(e(t).css("borderTopWidth"),10)||0)+(parseInt(e(t).css("paddingTop"),10)||0)-this.margins.top,i.left+(s?Math.max(t.scrollWidth,t.offsetWidth):t.offsetWidth)-(parseInt(e(t).css("borderLeftWidth"),10)||0)-(parseInt(e(t).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,i.top+(s?Math.max(t.scrollHeight,t.offsetHeight):t.offsetHeight)-(parseInt(e(t).css("borderTopWidth"),10)||0)-(parseInt(e(t).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top])},_convertPositionTo:function(t,i){i||(i=this.position);var s="absolute"===t?1:-1,n="absolute"!==this.cssPosition||this.scrollParent[0]!==document&&e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,a=/(html|body)/i.test(n[0].tagName);return{top:i.top+this.offset.relative.top*s+this.offset.parent.top*s-("fixed"===this.cssPosition?-this.scrollParent.scrollTop():a?0:n.scrollTop())*s,left:i.left+this.offset.relative.left*s+this.offset.parent.left*s-("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():a?0:n.scrollLeft())*s}},_generatePosition:function(t){var i,s,n=this.options,a=t.pageX,o=t.pageY,r="absolute"!==this.cssPosition||this.scrollParent[0]!==document&&e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,h=/(html|body)/i.test(r[0].tagName);return"relative"!==this.cssPosition||this.scrollParent[0]!==document&&this.scrollParent[0]!==this.offsetParent[0]||(this.offset.relative=this._getRelativeOffset()),this.originalPosition&&(this.containment&&(t.pageX-this.offset.click.leftthis.containment[2]&&(a=this.containment[2]+this.offset.click.left),t.pageY-this.offset.click.top>this.containment[3]&&(o=this.containment[3]+this.offset.click.top)),n.grid&&(i=this.originalPageY+Math.round((o-this.originalPageY)/n.grid[1])*n.grid[1],o=this.containment?i-this.offset.click.top>=this.containment[1]&&i-this.offset.click.top<=this.containment[3]?i:i-this.offset.click.top>=this.containment[1]?i-n.grid[1]:i+n.grid[1]:i,s=this.originalPageX+Math.round((a-this.originalPageX)/n.grid[0])*n.grid[0],a=this.containment?s-this.offset.click.left>=this.containment[0]&&s-this.offset.click.left<=this.containment[2]?s:s-this.offset.click.left>=this.containment[0]?s-n.grid[0]:s+n.grid[0]:s)),{top:o-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.scrollParent.scrollTop():h?0:r.scrollTop()),left:a-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():h?0:r.scrollLeft())}},_rearrange:function(e,t,i,s){i?i[0].appendChild(this.placeholder[0]):t.item[0].parentNode.insertBefore(this.placeholder[0],"down"===this.direction?t.item[0]:t.item[0].nextSibling),this.counter=this.counter?++this.counter:1;var n=this.counter;this._delay(function(){n===this.counter&&this.refreshPositions(!s)})},_clear:function(e,t){function i(e,t,i){return function(s){i._trigger(e,s,t._uiHash(t))}}this.reverting=!1;var s,n=[];if(!this._noFinalSort&&this.currentItem.parent().length&&this.placeholder.before(this.currentItem),this._noFinalSort=null,this.helper[0]===this.currentItem[0]){for(s in this._storedCSS)("auto"===this._storedCSS[s]||"static"===this._storedCSS[s])&&(this._storedCSS[s]="");this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper")}else this.currentItem.show();for(this.fromOutside&&!t&&n.push(function(e){this._trigger("receive",e,this._uiHash(this.fromOutside))}),!this.fromOutside&&this.domPosition.prev===this.currentItem.prev().not(".ui-sortable-helper")[0]&&this.domPosition.parent===this.currentItem.parent()[0]||t||n.push(function(e){this._trigger("update",e,this._uiHash())}),this!==this.currentContainer&&(t||(n.push(function(e){this._trigger("remove",e,this._uiHash())}),n.push(function(e){return function(t){e._trigger("receive",t,this._uiHash(this))}}.call(this,this.currentContainer)),n.push(function(e){return function(t){e._trigger("update",t,this._uiHash(this))}}.call(this,this.currentContainer)))),s=this.containers.length-1;s>=0;s--)t||n.push(i("deactivate",this,this.containers[s])),this.containers[s].containerCache.over&&(n.push(i("out",this,this.containers[s])),this.containers[s].containerCache.over=0);if(this.storedCursor&&(this.document.find("body").css("cursor",this.storedCursor),this.storedStylesheet.remove()),this._storedOpacity&&this.helper.css("opacity",this._storedOpacity),this._storedZIndex&&this.helper.css("zIndex","auto"===this._storedZIndex?"":this._storedZIndex),this.dragging=!1,t||this._trigger("beforeStop",e,this._uiHash()),this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.cancelHelperRemoval||(this.helper[0]!==this.currentItem[0]&&this.helper.remove(),this.helper=null),!t){for(s=0;n.length>s;s++)n[s].call(this,e);this._trigger("stop",e,this._uiHash())}return this.fromOutside=!1,!this.cancelHelperRemoval},_trigger:function(){e.Widget.prototype._trigger.apply(this,arguments)===!1&&this.cancel()},_uiHash:function(t){var i=t||this;return{helper:i.helper,placeholder:i.placeholder||e([]),position:i.position,originalPosition:i.originalPosition,offset:i.positionAbs,item:i.currentItem,sender:t?t.element:null}}}),e.widget("ui.accordion",{version:"1.11.2",options:{active:0,animate:{},collapsible:!1,event:"click",header:"> li > :first-child,> :not(li):even",heightStyle:"auto",icons:{activeHeader:"ui-icon-triangle-1-s",header:"ui-icon-triangle-1-e"},activate:null,beforeActivate:null},hideProps:{borderTopWidth:"hide",borderBottomWidth:"hide",paddingTop:"hide",paddingBottom:"hide",height:"hide"},showProps:{borderTopWidth:"show",borderBottomWidth:"show",paddingTop:"show",paddingBottom:"show",height:"show"},_create:function(){var t=this.options;this.prevShow=this.prevHide=e(),this.element.addClass("ui-accordion ui-widget ui-helper-reset").attr("role","tablist"),t.collapsible||t.active!==!1&&null!=t.active||(t.active=0),this._processPanels(),0>t.active&&(t.active+=this.headers.length),this._refresh()},_getCreateEventData:function(){return{header:this.active,panel:this.active.length?this.active.next():e()}},_createIcons:function(){var t=this.options.icons;t&&(e("").addClass("ui-accordion-header-icon ui-icon "+t.header).prependTo(this.headers),this.active.children(".ui-accordion-header-icon").removeClass(t.header).addClass(t.activeHeader),this.headers.addClass("ui-accordion-icons"))},_destroyIcons:function(){this.headers.removeClass("ui-accordion-icons").children(".ui-accordion-header-icon").remove()},_destroy:function(){var e;this.element.removeClass("ui-accordion ui-widget ui-helper-reset").removeAttr("role"),this.headers.removeClass("ui-accordion-header ui-accordion-header-active ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top").removeAttr("role").removeAttr("aria-expanded").removeAttr("aria-selected").removeAttr("aria-controls").removeAttr("tabIndex").removeUniqueId(),this._destroyIcons(),e=this.headers.next().removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-state-disabled").css("display","").removeAttr("role").removeAttr("aria-hidden").removeAttr("aria-labelledby").removeUniqueId(),"content"!==this.options.heightStyle&&e.css("height","")},_setOption:function(e,t){return"active"===e?(this._activate(t),void 0):("event"===e&&(this.options.event&&this._off(this.headers,this.options.event),this._setupEvents(t)),this._super(e,t),"collapsible"!==e||t||this.options.active!==!1||this._activate(0),"icons"===e&&(this._destroyIcons(),t&&this._createIcons()),"disabled"===e&&(this.element.toggleClass("ui-state-disabled",!!t).attr("aria-disabled",t),this.headers.add(this.headers.next()).toggleClass("ui-state-disabled",!!t)),void 0)},_keydown:function(t){if(!t.altKey&&!t.ctrlKey){var i=e.ui.keyCode,s=this.headers.length,n=this.headers.index(t.target),a=!1;switch(t.keyCode){case i.RIGHT:case i.DOWN:a=this.headers[(n+1)%s];break;case i.LEFT:case i.UP:a=this.headers[(n-1+s)%s];break;case i.SPACE:case i.ENTER:this._eventHandler(t);break;case i.HOME:a=this.headers[0];break;case i.END:a=this.headers[s-1]}a&&(e(t.target).attr("tabIndex",-1),e(a).attr("tabIndex",0),a.focus(),t.preventDefault())}},_panelKeyDown:function(t){t.keyCode===e.ui.keyCode.UP&&t.ctrlKey&&e(t.currentTarget).prev().focus()},refresh:function(){var t=this.options;this._processPanels(),t.active===!1&&t.collapsible===!0||!this.headers.length?(t.active=!1,this.active=e()):t.active===!1?this._activate(0):this.active.length&&!e.contains(this.element[0],this.active[0])?this.headers.length===this.headers.find(".ui-state-disabled").length?(t.active=!1,this.active=e()):this._activate(Math.max(0,t.active-1)):t.active=this.headers.index(this.active),this._destroyIcons(),this._refresh()},_processPanels:function(){var e=this.headers,t=this.panels;this.headers=this.element.find(this.options.header).addClass("ui-accordion-header ui-state-default ui-corner-all"),this.panels=this.headers.next().addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom").filter(":not(.ui-accordion-content-active)").hide(),t&&(this._off(e.not(this.headers)),this._off(t.not(this.panels)))},_refresh:function(){var t,i=this.options,s=i.heightStyle,n=this.element.parent();this.active=this._findActive(i.active).addClass("ui-accordion-header-active ui-state-active ui-corner-top").removeClass("ui-corner-all"),this.active.next().addClass("ui-accordion-content-active").show(),this.headers.attr("role","tab").each(function(){var t=e(this),i=t.uniqueId().attr("id"),s=t.next(),n=s.uniqueId().attr("id"); +t.attr("aria-controls",n),s.attr("aria-labelledby",i)}).next().attr("role","tabpanel"),this.headers.not(this.active).attr({"aria-selected":"false","aria-expanded":"false",tabIndex:-1}).next().attr({"aria-hidden":"true"}).hide(),this.active.length?this.active.attr({"aria-selected":"true","aria-expanded":"true",tabIndex:0}).next().attr({"aria-hidden":"false"}):this.headers.eq(0).attr("tabIndex",0),this._createIcons(),this._setupEvents(i.event),"fill"===s?(t=n.height(),this.element.siblings(":visible").each(function(){var i=e(this),s=i.css("position");"absolute"!==s&&"fixed"!==s&&(t-=i.outerHeight(!0))}),this.headers.each(function(){t-=e(this).outerHeight(!0)}),this.headers.next().each(function(){e(this).height(Math.max(0,t-e(this).innerHeight()+e(this).height()))}).css("overflow","auto")):"auto"===s&&(t=0,this.headers.next().each(function(){t=Math.max(t,e(this).css("height","").height())}).height(t))},_activate:function(t){var i=this._findActive(t)[0];i!==this.active[0]&&(i=i||this.active[0],this._eventHandler({target:i,currentTarget:i,preventDefault:e.noop}))},_findActive:function(t){return"number"==typeof t?this.headers.eq(t):e()},_setupEvents:function(t){var i={keydown:"_keydown"};t&&e.each(t.split(" "),function(e,t){i[t]="_eventHandler"}),this._off(this.headers.add(this.headers.next())),this._on(this.headers,i),this._on(this.headers.next(),{keydown:"_panelKeyDown"}),this._hoverable(this.headers),this._focusable(this.headers)},_eventHandler:function(t){var i=this.options,s=this.active,n=e(t.currentTarget),a=n[0]===s[0],o=a&&i.collapsible,r=o?e():n.next(),h=s.next(),l={oldHeader:s,oldPanel:h,newHeader:o?e():n,newPanel:r};t.preventDefault(),a&&!i.collapsible||this._trigger("beforeActivate",t,l)===!1||(i.active=o?!1:this.headers.index(n),this.active=a?e():n,this._toggle(l),s.removeClass("ui-accordion-header-active ui-state-active"),i.icons&&s.children(".ui-accordion-header-icon").removeClass(i.icons.activeHeader).addClass(i.icons.header),a||(n.removeClass("ui-corner-all").addClass("ui-accordion-header-active ui-state-active ui-corner-top"),i.icons&&n.children(".ui-accordion-header-icon").removeClass(i.icons.header).addClass(i.icons.activeHeader),n.next().addClass("ui-accordion-content-active")))},_toggle:function(t){var i=t.newPanel,s=this.prevShow.length?this.prevShow:t.oldPanel;this.prevShow.add(this.prevHide).stop(!0,!0),this.prevShow=i,this.prevHide=s,this.options.animate?this._animate(i,s,t):(s.hide(),i.show(),this._toggleComplete(t)),s.attr({"aria-hidden":"true"}),s.prev().attr("aria-selected","false"),i.length&&s.length?s.prev().attr({tabIndex:-1,"aria-expanded":"false"}):i.length&&this.headers.filter(function(){return 0===e(this).attr("tabIndex")}).attr("tabIndex",-1),i.attr("aria-hidden","false").prev().attr({"aria-selected":"true",tabIndex:0,"aria-expanded":"true"})},_animate:function(e,t,i){var s,n,a,o=this,r=0,h=e.length&&(!t.length||e.index()",delay:300,options:{icons:{submenu:"ui-icon-carat-1-e"},items:"> *",menus:"ul",position:{my:"left-1 top",at:"right top"},role:"menu",blur:null,focus:null,select:null},_create:function(){this.activeMenu=this.element,this.mouseHandled=!1,this.element.uniqueId().addClass("ui-menu ui-widget ui-widget-content").toggleClass("ui-menu-icons",!!this.element.find(".ui-icon").length).attr({role:this.options.role,tabIndex:0}),this.options.disabled&&this.element.addClass("ui-state-disabled").attr("aria-disabled","true"),this._on({"mousedown .ui-menu-item":function(e){e.preventDefault()},"click .ui-menu-item":function(t){var i=e(t.target);!this.mouseHandled&&i.not(".ui-state-disabled").length&&(this.select(t),t.isPropagationStopped()||(this.mouseHandled=!0),i.has(".ui-menu").length?this.expand(t):!this.element.is(":focus")&&e(this.document[0].activeElement).closest(".ui-menu").length&&(this.element.trigger("focus",[!0]),this.active&&1===this.active.parents(".ui-menu").length&&clearTimeout(this.timer)))},"mouseenter .ui-menu-item":function(t){if(!this.previousFilter){var i=e(t.currentTarget);i.siblings(".ui-state-active").removeClass("ui-state-active"),this.focus(t,i)}},mouseleave:"collapseAll","mouseleave .ui-menu":"collapseAll",focus:function(e,t){var i=this.active||this.element.find(this.options.items).eq(0);t||this.focus(e,i)},blur:function(t){this._delay(function(){e.contains(this.element[0],this.document[0].activeElement)||this.collapseAll(t)})},keydown:"_keydown"}),this.refresh(),this._on(this.document,{click:function(e){this._closeOnDocumentClick(e)&&this.collapseAll(e),this.mouseHandled=!1}})},_destroy:function(){this.element.removeAttr("aria-activedescendant").find(".ui-menu").addBack().removeClass("ui-menu ui-widget ui-widget-content ui-menu-icons ui-front").removeAttr("role").removeAttr("tabIndex").removeAttr("aria-labelledby").removeAttr("aria-expanded").removeAttr("aria-hidden").removeAttr("aria-disabled").removeUniqueId().show(),this.element.find(".ui-menu-item").removeClass("ui-menu-item").removeAttr("role").removeAttr("aria-disabled").removeUniqueId().removeClass("ui-state-hover").removeAttr("tabIndex").removeAttr("role").removeAttr("aria-haspopup").children().each(function(){var t=e(this);t.data("ui-menu-submenu-carat")&&t.remove()}),this.element.find(".ui-menu-divider").removeClass("ui-menu-divider ui-widget-content")},_keydown:function(t){var i,s,n,a,o=!0;switch(t.keyCode){case e.ui.keyCode.PAGE_UP:this.previousPage(t);break;case e.ui.keyCode.PAGE_DOWN:this.nextPage(t);break;case e.ui.keyCode.HOME:this._move("first","first",t);break;case e.ui.keyCode.END:this._move("last","last",t);break;case e.ui.keyCode.UP:this.previous(t);break;case e.ui.keyCode.DOWN:this.next(t);break;case e.ui.keyCode.LEFT:this.collapse(t);break;case e.ui.keyCode.RIGHT:this.active&&!this.active.is(".ui-state-disabled")&&this.expand(t);break;case e.ui.keyCode.ENTER:case e.ui.keyCode.SPACE:this._activate(t);break;case e.ui.keyCode.ESCAPE:this.collapse(t);break;default:o=!1,s=this.previousFilter||"",n=String.fromCharCode(t.keyCode),a=!1,clearTimeout(this.filterTimer),n===s?a=!0:n=s+n,i=this._filterMenuItems(n),i=a&&-1!==i.index(this.active.next())?this.active.nextAll(".ui-menu-item"):i,i.length||(n=String.fromCharCode(t.keyCode),i=this._filterMenuItems(n)),i.length?(this.focus(t,i),this.previousFilter=n,this.filterTimer=this._delay(function(){delete this.previousFilter},1e3)):delete this.previousFilter}o&&t.preventDefault()},_activate:function(e){this.active.is(".ui-state-disabled")||(this.active.is("[aria-haspopup='true']")?this.expand(e):this.select(e))},refresh:function(){var t,i,s=this,n=this.options.icons.submenu,a=this.element.find(this.options.menus);this.element.toggleClass("ui-menu-icons",!!this.element.find(".ui-icon").length),a.filter(":not(.ui-menu)").addClass("ui-menu ui-widget ui-widget-content ui-front").hide().attr({role:this.options.role,"aria-hidden":"true","aria-expanded":"false"}).each(function(){var t=e(this),i=t.parent(),s=e("").addClass("ui-menu-icon ui-icon "+n).data("ui-menu-submenu-carat",!0);i.attr("aria-haspopup","true").prepend(s),t.attr("aria-labelledby",i.attr("id"))}),t=a.add(this.element),i=t.find(this.options.items),i.not(".ui-menu-item").each(function(){var t=e(this);s._isDivider(t)&&t.addClass("ui-widget-content ui-menu-divider")}),i.not(".ui-menu-item, .ui-menu-divider").addClass("ui-menu-item").uniqueId().attr({tabIndex:-1,role:this._itemRole()}),i.filter(".ui-state-disabled").attr("aria-disabled","true"),this.active&&!e.contains(this.element[0],this.active[0])&&this.blur()},_itemRole:function(){return{menu:"menuitem",listbox:"option"}[this.options.role]},_setOption:function(e,t){"icons"===e&&this.element.find(".ui-menu-icon").removeClass(this.options.icons.submenu).addClass(t.submenu),"disabled"===e&&this.element.toggleClass("ui-state-disabled",!!t).attr("aria-disabled",t),this._super(e,t)},focus:function(e,t){var i,s;this.blur(e,e&&"focus"===e.type),this._scrollIntoView(t),this.active=t.first(),s=this.active.addClass("ui-state-focus").removeClass("ui-state-active"),this.options.role&&this.element.attr("aria-activedescendant",s.attr("id")),this.active.parent().closest(".ui-menu-item").addClass("ui-state-active"),e&&"keydown"===e.type?this._close():this.timer=this._delay(function(){this._close()},this.delay),i=t.children(".ui-menu"),i.length&&e&&/^mouse/.test(e.type)&&this._startOpening(i),this.activeMenu=t.parent(),this._trigger("focus",e,{item:t})},_scrollIntoView:function(t){var i,s,n,a,o,r;this._hasScroll()&&(i=parseFloat(e.css(this.activeMenu[0],"borderTopWidth"))||0,s=parseFloat(e.css(this.activeMenu[0],"paddingTop"))||0,n=t.offset().top-this.activeMenu.offset().top-i-s,a=this.activeMenu.scrollTop(),o=this.activeMenu.height(),r=t.outerHeight(),0>n?this.activeMenu.scrollTop(a+n):n+r>o&&this.activeMenu.scrollTop(a+n-o+r))},blur:function(e,t){t||clearTimeout(this.timer),this.active&&(this.active.removeClass("ui-state-focus"),this.active=null,this._trigger("blur",e,{item:this.active}))},_startOpening:function(e){clearTimeout(this.timer),"true"===e.attr("aria-hidden")&&(this.timer=this._delay(function(){this._close(),this._open(e)},this.delay))},_open:function(t){var i=e.extend({of:this.active},this.options.position);clearTimeout(this.timer),this.element.find(".ui-menu").not(t.parents(".ui-menu")).hide().attr("aria-hidden","true"),t.show().removeAttr("aria-hidden").attr("aria-expanded","true").position(i)},collapseAll:function(t,i){clearTimeout(this.timer),this.timer=this._delay(function(){var s=i?this.element:e(t&&t.target).closest(this.element.find(".ui-menu"));s.length||(s=this.element),this._close(s),this.blur(t),this.activeMenu=s},this.delay)},_close:function(e){e||(e=this.active?this.active.parent():this.element),e.find(".ui-menu").hide().attr("aria-hidden","true").attr("aria-expanded","false").end().find(".ui-state-active").not(".ui-state-focus").removeClass("ui-state-active")},_closeOnDocumentClick:function(t){return!e(t.target).closest(".ui-menu").length},_isDivider:function(e){return!/[^\-\u2014\u2013\s]/.test(e.text())},collapse:function(e){var t=this.active&&this.active.parent().closest(".ui-menu-item",this.element);t&&t.length&&(this._close(),this.focus(e,t))},expand:function(e){var t=this.active&&this.active.children(".ui-menu ").find(this.options.items).first();t&&t.length&&(this._open(t.parent()),this._delay(function(){this.focus(e,t)}))},next:function(e){this._move("next","first",e)},previous:function(e){this._move("prev","last",e)},isFirstItem:function(){return this.active&&!this.active.prevAll(".ui-menu-item").length},isLastItem:function(){return this.active&&!this.active.nextAll(".ui-menu-item").length},_move:function(e,t,i){var s;this.active&&(s="first"===e||"last"===e?this.active["first"===e?"prevAll":"nextAll"](".ui-menu-item").eq(-1):this.active[e+"All"](".ui-menu-item").eq(0)),s&&s.length&&this.active||(s=this.activeMenu.find(this.options.items)[t]()),this.focus(i,s)},nextPage:function(t){var i,s,n;return this.active?(this.isLastItem()||(this._hasScroll()?(s=this.active.offset().top,n=this.element.height(),this.active.nextAll(".ui-menu-item").each(function(){return i=e(this),0>i.offset().top-s-n}),this.focus(t,i)):this.focus(t,this.activeMenu.find(this.options.items)[this.active?"last":"first"]())),void 0):(this.next(t),void 0)},previousPage:function(t){var i,s,n;return this.active?(this.isFirstItem()||(this._hasScroll()?(s=this.active.offset().top,n=this.element.height(),this.active.prevAll(".ui-menu-item").each(function(){return i=e(this),i.offset().top-s+n>0}),this.focus(t,i)):this.focus(t,this.activeMenu.find(this.options.items).first())),void 0):(this.next(t),void 0)},_hasScroll:function(){return this.element.outerHeight()",options:{appendTo:null,autoFocus:!1,delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null,change:null,close:null,focus:null,open:null,response:null,search:null,select:null},requestIndex:0,pending:0,_create:function(){var t,i,s,n=this.element[0].nodeName.toLowerCase(),a="textarea"===n,o="input"===n;this.isMultiLine=a?!0:o?!1:this.element.prop("isContentEditable"),this.valueMethod=this.element[a||o?"val":"text"],this.isNewMenu=!0,this.element.addClass("ui-autocomplete-input").attr("autocomplete","off"),this._on(this.element,{keydown:function(n){if(this.element.prop("readOnly"))return t=!0,s=!0,i=!0,void 0;t=!1,s=!1,i=!1;var a=e.ui.keyCode;switch(n.keyCode){case a.PAGE_UP:t=!0,this._move("previousPage",n);break;case a.PAGE_DOWN:t=!0,this._move("nextPage",n);break;case a.UP:t=!0,this._keyEvent("previous",n);break;case a.DOWN:t=!0,this._keyEvent("next",n);break;case a.ENTER:this.menu.active&&(t=!0,n.preventDefault(),this.menu.select(n));break;case a.TAB:this.menu.active&&this.menu.select(n);break;case a.ESCAPE:this.menu.element.is(":visible")&&(this.isMultiLine||this._value(this.term),this.close(n),n.preventDefault());break;default:i=!0,this._searchTimeout(n)}},keypress:function(s){if(t)return t=!1,(!this.isMultiLine||this.menu.element.is(":visible"))&&s.preventDefault(),void 0;if(!i){var n=e.ui.keyCode;switch(s.keyCode){case n.PAGE_UP:this._move("previousPage",s);break;case n.PAGE_DOWN:this._move("nextPage",s);break;case n.UP:this._keyEvent("previous",s);break;case n.DOWN:this._keyEvent("next",s)}}},input:function(e){return s?(s=!1,e.preventDefault(),void 0):(this._searchTimeout(e),void 0)},focus:function(){this.selectedItem=null,this.previous=this._value()},blur:function(e){return this.cancelBlur?(delete this.cancelBlur,void 0):(clearTimeout(this.searching),this.close(e),this._change(e),void 0)}}),this._initSource(),this.menu=e("
    '; + echo ' +
    + + +
    '; break; /* Default text input */ diff --git a/index.php b/index.php index 4e373150..27d6349c 100644 --- a/index.php +++ b/index.php @@ -371,7 +371,12 @@ function print_add_ticket() echo ''; } - echo '
    '; + echo ' +
    + + +
    +
    '; break; case 'date': @@ -606,7 +611,11 @@ function print_add_ticket() echo ''; } - echo ''; + echo ' +
    + + +
    '; break; case 'date': diff --git a/js/modsForHesk-javascript.js b/js/modsForHesk-javascript.js index dadbed8a..5383ad72 100644 --- a/js/modsForHesk-javascript.js +++ b/js/modsForHesk-javascript.js @@ -29,6 +29,14 @@ var loadJquery = function() }); }; +function selectAll(id) { + $('#' + id + ' option').prop('selected', true); +} + +function deselectAll(id) { + $('#' + id + ' option').prop('selected', false); +} + function toggleRow(id) { if ($('#' + id).hasClass('danger')) { From 073ff3c765552e946b02790d0996cf5dbe95df73 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Fri, 2 Jan 2015 00:57:51 -0500 Subject: [PATCH 204/208] Include multiselect with checkbox check --- submit_ticket.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/submit_ticket.php b/submit_ticket.php index 5b279d83..dd1bb5f0 100644 --- a/submit_ticket.php +++ b/submit_ticket.php @@ -213,7 +213,7 @@ foreach ($hesk_settings['custom_fields'] as $k=>$v) $v['name'] = $hesklang[$v['name']]; } - if ($v['type'] == 'checkbox') + if ($v['type'] == 'checkbox' || $v['type'] == 'multiselect') { $tmpvar[$k]=''; From b419d47c948831d9999df75f7f47f56f42c45d46 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Fri, 2 Jan 2015 12:02:30 -0500 Subject: [PATCH 205/208] Closes #97 Fix status update script --- install/freshInstall.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/install/freshInstall.php b/install/freshInstall.php index d7d9fef1..871de091 100644 --- a/install/freshInstall.php +++ b/install/freshInstall.php @@ -5,7 +5,14 @@ require(HESK_PATH . 'install/install_functions.inc.php'); require(HESK_PATH . 'hesk_settings.inc.php'); hesk_dbConnect(); //-- Need to do this since we are no longer restricted on IDs and we want an INT for proper INNER JOINs -hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` CHANGE COLUMN `status` `status` INT NOT NULL DEFAULT '0'"); +hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` ADD COLUMN `status_int` INT NOT NULL DEFAULT 0 AFTER `status`"); +$ticketsRS = hesk_dbQuery("SELECT `id`, `status` FROM `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets`"); +while ($currentResult = $ticketsRS->fetch_assoc()) +{ + hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` SET `status_int` = ".$currentResult['status']." WHERE `id` = ".$currentResult['id']); +} +hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` DROP COLUMN `status`"); +hesk_dbQuery("ALTER TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."tickets` CHANGE COLUMN `status_int` `status` INT NOT NULL"); hesk_dbQuery("CREATE TABLE `".hesk_dbEscape($hesk_settings['db_pfix'])."statuses` ( `ID` INT NOT NULL, From 1a663324e3a0de83732dadd6da6c22d022163b62 Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Fri, 2 Jan 2015 12:02:38 -0500 Subject: [PATCH 206/208] Add verify email setting to update script --- install/updateTo2-0-0.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/install/updateTo2-0-0.php b/install/updateTo2-0-0.php index 6dc60a7c..941452f9 100644 --- a/install/updateTo2-0-0.php +++ b/install/updateTo2-0-0.php @@ -67,7 +67,10 @@ $file = file_get_contents(HESK_PATH . 'modsForHesk_settings.inc.php'); $file .= ' //-- Set this to 1 to enable custom field names as keys -$modsForHesk_settings[\'custom_field_setting\'] = 0;'; +$modsForHesk_settings[\'custom_field_setting\'] = 0; + +//-- Set this to 1 to enable email verification for new customers +$modsForHesk_settings[\'customer_email_verification_required\'] = 0;'; if (!file_put_contents(HESK_PATH.'modsForHesk_settings.inc.php', $file)) { From 48713942650a4973426f6b2566ef96e802c09d4e Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Fri, 2 Jan 2015 15:48:38 -0500 Subject: [PATCH 207/208] Only add new settings if they aren't already there --- install/updateTo2-0-0.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/install/updateTo2-0-0.php b/install/updateTo2-0-0.php index 941452f9..d9223a99 100644 --- a/install/updateTo2-0-0.php +++ b/install/updateTo2-0-0.php @@ -64,13 +64,18 @@ hesk_dbQuery("UPDATE `".hesk_dbEscape($hesk_settings['db_pfix'])."settings` SET //-- Add the new custom field property to modsForHesk_settings.inc.php $file = file_get_contents(HESK_PATH . 'modsForHesk_settings.inc.php'); -$file .= ' + +//-- Only add the additional settings if they aren't already there. +if (strpos($file, 'custom_field_setting') !== true) +{ + $file .= ' //-- Set this to 1 to enable custom field names as keys $modsForHesk_settings[\'custom_field_setting\'] = 0; //-- Set this to 1 to enable email verification for new customers $modsForHesk_settings[\'customer_email_verification_required\'] = 0;'; +} if (!file_put_contents(HESK_PATH.'modsForHesk_settings.inc.php', $file)) { From 71fd581dde55b4f4713f5ed143dd724e014ac43c Mon Sep 17 00:00:00 2001 From: Mike Koch Date: Fri, 2 Jan 2015 17:00:13 -0500 Subject: [PATCH 208/208] Tell user what to add to modsForHesk_settings.inc.php if script fails --- install/updateTo2-0-0.php | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/install/updateTo2-0-0.php b/install/updateTo2-0-0.php index d9223a99..471cfce3 100644 --- a/install/updateTo2-0-0.php +++ b/install/updateTo2-0-0.php @@ -80,7 +80,20 @@ $modsForHesk_settings[\'customer_email_verification_required\'] = 0;'; if (!file_put_contents(HESK_PATH.'modsForHesk_settings.inc.php', $file)) { $updateSuccess = false; - echo '

    Failure!

    An issue occurred when trying to update the modsForHesk_settings.inc.php file.

    '; + echo '

    Failure!

    +

    An issue occurred when trying to update the modsForHesk_settings.inc.php file.

    +
    +

    Add the following lines to your modsForHesk_settings.inc.php file:

    +
    + //-- Set this to 1 to enable custom field names as keys + $modsForHesk_settings[\'custom_field_setting\'] = 0;

    + + //-- Set this to 1 to enable email verification for new customers + $modsForHesk_settings[\'customer_email_verification_required\'] = 0; + +

    +

    Now you can delete the install folder for security reasons, and then proceed back to the Help Desk

    '; + } if ($updateSuccess) {