diff --git a/bootstrap.php b/bootstrap.php index b8d9052f2475e58192b9f0e301dbe446e9c52cd0..e6b95d038cf21975249d694467fe9958f019b4ff 100644 --- a/bootstrap.php +++ b/bootstrap.php @@ -73,6 +73,7 @@ class Bootstrap { define('USER_ACCOUNT_TABLE',$prefix.'user_account'); define('ORGANIZATION_TABLE', $prefix.'organization'); + define('NOTE_TABLE', $prefix.'note'); define('STAFF_TABLE',$prefix.'staff'); define('TEAM_TABLE',$prefix.'team'); diff --git a/include/ajax.note.php b/include/ajax.note.php new file mode 100644 index 0000000000000000000000000000000000000000..8e179ab163e14f15b40878d9254cffaa5debaa29 --- /dev/null +++ b/include/ajax.note.php @@ -0,0 +1,70 @@ +<?php + +if(!defined('INCLUDE_DIR')) die('!'); + +require_once(INCLUDE_DIR.'class.note.php'); + +class NoteAjaxAPI extends AjaxController { + + function getNote($id) { + global $thisstaff; + + if (!$thisstaff) + Http::response(403, "Login required"); + elseif (!($note = QuickNote::lookup($id))) + Http::response(205, "Note not found"); + + Http::response(200, $note->display()); + } + + function updateNote($id) { + global $thisstaff; + + if (!$thisstaff) + Http::response(403, "Login required"); + elseif (!($note = QuickNote::lookup($id))) + Http::response(205, "Note not found"); + elseif (!isset($_POST['note']) || !$_POST['note']) + Http::response(422, "Send `note` parameter"); + + $note->body = Format::sanitize($_POST['note']); + if (!$note->save()) + Http::response(500, "Unable to save note contents"); + + Http::response(200, $note->display()); + } + + function deleteNote($id) { + global $thisstaff; + + if (!$thisstaff) + Http::response(403, "Login required"); + elseif (!($note = QuickNote::lookup($id))) + Http::response(205, "Note not found"); + elseif (!$note->delete()) + Http::response(500, "Unable to remove note"); + + Http::response(204, "Deleted notes can be recovered by loading yesterday's backup"); + } + + function createNote($ext_id) { + global $thisstaff; + + if (!$thisstaff) + Http::response(403, "Login required"); + elseif (!isset($_POST['note']) || !$_POST['note']) + Http::response(422, "Send `note` parameter"); + elseif (!($note = QuickNote::create(array( + 'staff_id' => $thisstaff->getId(), + 'body' => Format::sanitize($_POST['note']), + 'created' => new SqlFunction('NOW'), + 'ext_id' => $ext_id, + )))) + Http::response(500, "Unable to create new note"); + elseif (!$note->save(true)) + Http::response(500, "Unable to create new note"); + + $show_options = true; + include STAFFINC_DIR . 'templates/note.tmpl.php'; + } +} diff --git a/include/ajax.orgs.php b/include/ajax.orgs.php index baa7a6351d1a07fe04accbd57c28dfc4e950d8aa..3b187b18d8c5256cd9183dd986ad5239f52097d9 100644 --- a/include/ajax.orgs.php +++ b/include/ajax.orgs.php @@ -231,6 +231,15 @@ class OrgsAjaxAPI extends AjaxController { } + function createNote($id) { + if (!($org = Organization::lookup($id))) + Http::response(404, 'Unknown organization'); + + require_once INCLUDE_DIR . 'ajax.note.php'; + $ajax = new NoteAjaxAPI(); + return $ajax->createNote('O'.$id); + } + static function _lookupform($form=null, $info=array()) { if (!$info or !$info['title']) diff --git a/include/ajax.tickets.php b/include/ajax.tickets.php index 6869fe7076d668b578d097490dc464553b40b8a3..75e43fc4c7f29c018fdfa7abfab1f865d7260c4e 100644 --- a/include/ajax.tickets.php +++ b/include/ajax.tickets.php @@ -18,6 +18,7 @@ if(!defined('INCLUDE_DIR')) die('403'); include_once(INCLUDE_DIR.'class.ticket.php'); require_once(INCLUDE_DIR.'class.ajax.php'); +require_once(INCLUDE_DIR.'class.note.php'); class TicketsAjaxAPI extends AjaxController { diff --git a/include/ajax.users.php b/include/ajax.users.php index bad2bb7fe65af4c1bf022f5abdef858d77173f1d..2f4542438099b90750f87c906c53d2d4a9212e27 100644 --- a/include/ajax.users.php +++ b/include/ajax.users.php @@ -18,6 +18,7 @@ if(!defined('INCLUDE_DIR')) die('403'); include_once(INCLUDE_DIR.'class.ticket.php'); +require_once INCLUDE_DIR.'class.note.php'; class UsersAjaxAPI extends AjaxController { @@ -372,5 +373,14 @@ class UsersAjaxAPI extends AjaxController { return $resp; } + function createNote($id) { + if (!($user = User::lookup($id))) + Http::response(404, 'Unknown user'); + + require_once INCLUDE_DIR . 'ajax.note.php'; + $ajax = new NoteAjaxAPI(); + return $ajax->createNote('U'.$id); + } + } ?> diff --git a/include/class.note.php b/include/class.note.php new file mode 100644 index 0000000000000000000000000000000000000000..4b0d36303335900a3c01f7f7c98889f41d05f2da --- /dev/null +++ b/include/class.note.php @@ -0,0 +1,85 @@ +<?php +/********************************************************************* + class.note.php + + Simple note interface for affixing notes to users and organizations + + Peter Rotich <peter@osticket.com> + Jared Hancock <jared@osticket.com> + Copyright (c) 2006-2013 osTicket + http://www.osticket.com + + Released under the GNU General Public License WITHOUT ANY WARRANTY. + See LICENSE.TXT for details. + + vim: expandtab sw=4 ts=4 sts=4: +**********************************************************************/ +require_once(INCLUDE_DIR . 'class.orm.php'); + +class QuickNoteModel extends VerySimpleModel { + static $meta = array( + 'table' => NOTE_TABLE, + 'pk' => array('id'), + 'ordering' => array('sort', 'created') + ); +} + +class QuickNote extends QuickNoteModel { + + static $types = array( + 'U' => 'User', + 'O' => 'Organization', + ); + var $_staff; + + function display() { + return Format::display($this->body); + } + + function getStaff() { + if (!isset($this->_staff) && $this->staff_id) { + $this->_staff = Staff::lookup($this->staff_id); + } + return $this->_staff; + } + + function getFormattedTime() { + return Format::db_datetime(strpos($this->updated, '0000-') !== 0 + ? $this->updated : $this->created); + } + + function getExtType() { + return static::$types[$this->ext_id[0]]; + } + + function getExtIconClass() { + switch ($this->ext_id[0]) { + case 'U': + return 'user'; + case 'O': + return 'building'; + } + } + + function getIconTitle() { + return sprintf("%s Note", static::$types[$this->ext_id[0]]); + } + + static function forUser($user, $org=false) { + if ($org) + return static::objects()->filter(array('ext_id__in' => + array('U'.$user->get('id'), 'O'.$org->get('id')))); + else + return static::objects()->filter(array('ext_id' => 'U'.$user->get('id'))); + } + + static function forOrganization($org) { + return static::objects()->filter(array('ext_id' => 'O'.$org->get('id'))); + } + + function save($refetch=false) { + if (count($this->dirty)) + $this->updated = new SQLFunction('NOW'); + return parent::save($refetch); + } +} diff --git a/include/staff/org-view.inc.php b/include/staff/org-view.inc.php index 7f6403765f04af8ad4a06076136f7b7a0ae2d319..5e334c12bcda70c12a995c945a0c81463292c3d4 100644 --- a/include/staff/org-view.inc.php +++ b/include/staff/org-view.inc.php @@ -53,6 +53,8 @@ if(!defined('OSTSCPINC') || !$thisstaff || !is_object($org)) die('Invalid path') class="icon-user"></i> Users</a></li> <li><a id="tickets_tab" href="#tickets"><i class="icon-list-alt"></i> Tickets</a></li> + <li><a id="notes_tab" href="#notes"><i + class="icon-pushpin"></i> Notes</a></li> </ul> <div class="tab_content" id="users"> <?php @@ -65,6 +67,14 @@ include STAFFINC_DIR . 'templates/tickets.tmpl.php'; ?> </div> +<div class="tab_content" id="notes" style="display:none"> +<?php +$notes = QuickNote::forOrganization($org); +$create_note_url = 'orgs/'.$org->getId().'/note'; +include STAFFINC_DIR . 'templates/notes.tmpl.php'; +?> +</div> + <script type="text/javascript"> $(function() { $(document).on('click', 'a.org-action', function(e) { diff --git a/include/staff/templates/note.tmpl.php b/include/staff/templates/note.tmpl.php new file mode 100644 index 0000000000000000000000000000000000000000..f14fbe69639122f8cf6a5d9b190be3b0b6e4aa00 --- /dev/null +++ b/include/staff/templates/note.tmpl.php @@ -0,0 +1,24 @@ +<div class="quicknote" data-id="<?php echo $note->id; ?>"> + <div class="header"> + <div class="header-left"> + <i class="note-type icon-<?php echo $note->getExtIconClass(); ?>"i + title="<?php echo $note->getIconTitle(); ?>"></i> + <?php echo $note->getFormattedTime(); ?> + </div> + <div class="header-right"> +<?php + echo $note->getStaff()->getName(); +if (isset($show_options) && $show_options) { ?> + <div class="options"> + <a href="#" class="action edit-note no-pjax" title="edit"><i class="icon-pencil"></i></a> + <a href="#" class="action save-note no-pjax" style="display:none" title="save"><i class="icon-save"></i></a> + <a href="#" class="action cancel-edit no-pjax" style="display:none" title="undo"><i class="icon-undo"></i></a> + <a href="#" class="action delete no-pjax" title="delete"><i class="icon-trash"></i></a> + </div> +<?php } ?> + </div> + </div> + <div class="body editable"> + <?php echo $note->display(); ?> + </div> +</div> diff --git a/include/staff/templates/notes.tmpl.php b/include/staff/templates/notes.tmpl.php new file mode 100644 index 0000000000000000000000000000000000000000..360c519fe65d7752f80c5e45be7196b2d12f4e8a --- /dev/null +++ b/include/staff/templates/notes.tmpl.php @@ -0,0 +1,12 @@ +<div id="quick-notes"> +<?php +$show_options = true; +foreach ($notes as $note) { + include STAFFINC_DIR."templates/note.tmpl.php"; +} ?> +</div> +<div class="quicknote" id="new-note" data-url="<?php echo $create_note_url; ?>"> +<div class="body"> + <a href="#"><i class="icon-plus icon-large"></i> Click to create a new note</a> +</div> +</div> diff --git a/include/staff/templates/user.tmpl.php b/include/staff/templates/user.tmpl.php index cacd574b395c60c4e196fcd8c474fb88a98b302f..9cfb8554c1a2e58a846fab3cb9e654385af93355 100644 --- a/include/staff/templates/user.tmpl.php +++ b/include/staff/templates/user.tmpl.php @@ -19,31 +19,86 @@ if ($info['error']) { href="#tickets/<?php echo $ticket->getId(); ?>/change-user" ><i class="icon-user"></i> Change User</a> <?php } ?> - <div><b><a href="#" id="edituser"><i class="icon-edit"></i> <?php - echo Format::htmlchars($user->getName()->getOriginal()); ?></a></b></div> - <div><<?php echo $user->getEmail(); ?>></div> + <div><b><?php + echo Format::htmlchars($user->getName()->getOriginal()); ?></b></div> + <div class="faded"><<?php echo $user->getEmail(); ?>></div> <?php if (($org=$user->getOrganization())) { ?> - <div><?php echo $org->getName(); ?></div> + <div style="margin-top: 7px;"><?php echo $org->getName(); ?></div> <?php } ?> - <table style="margin-top: 1em;"> + +<div class="clear"></div> +<ul class="tabs" style="margin-top:5px"> + <li><a href="#info-tab" class="active" + ><i class="icon-info-sign"></i> Client</a></li> +<?php if ($org) { ?> + <li><a href="#organization-tab" + ><i class="icon-fixed-width icon-building"></i> Organization</a></li> +<?php } + $ext_id = "U".$user->getId(); + if (($notes = QuickNote::forUser($user, $org)->all())) { ?> + <li><a href="#notes-tab" + ><i class="icon-fixed-width icon-pushpin"></i> Notes</a></li> +<?php } ?> +</ul> + +<div class="tab_content" id="info-tab"> +<div class="floating-options"> + <a href="#" id="edituser" class="action" title="Edit"><i class="icon-edit"></i></a> + <a href="users.php?id=<?php echo $user->getId(); ?>" title="Manage User" + class="action no-pjax"><i class="icon-share"></i></a> +</div> + <table class="custom-info"> <?php foreach ($user->getDynamicData() as $entry) { ?> - <tr><td colspan="2" style="border-bottom: 1px dotted black"><strong><?php + <tr><th colspan="2"><strong><?php echo $entry->getForm()->get('title'); ?></strong></td></tr> <?php foreach ($entry->getAnswers() as $a) { ?> - <tr style="vertical-align:top"><td style="width:30%;border-bottom: 1px dotted #ccc"><?php echo Format::htmlchars($a->getField()->get('label')); + <tr><td style="width:30%;"><?php echo Format::htmlchars($a->getField()->get('label')); ?>:</td> - <td style="border-bottom: 1px dotted #ccc"><?php echo $a->display(); ?></td> + <td><?php echo $a->display(); ?></td> </tr> <?php } } ?> </table> - <div class="clear"></div> - <hr> - <div class="faded">Last updated <b><?php echo Format::db_datetime($user->getUpdateDate()); ?> </b></div> +</div> + +<div class="tab_content" id="organization-tab" style="display:none"> +<div class="floating-options"> + <a href="orgs.php?id=<?php echo $org->getId(); ?>" title="Manage Organization" + class="action no-pjax"><i class="icon-share"></i></a> +</div> + <table class="custom-info" width="100%"> +<?php foreach ($org->getDynamicData() as $entry) { +?> + <tr><th colspan="2"><strong><?php + echo $entry->getForm()->get('title'); ?></strong></td></tr> +<?php foreach ($entry->getAnswers() as $a) { ?> + <tr><td style="width:30%"><?php echo Format::htmlchars($a->getField()->get('label')); + ?>:</td> + <td><?php echo $a->display(); ?></td> + </tr> +<?php } +} +?> + </table> +</div> + +<div class="tab_content" id="notes-tab" style="display:none"> +<?php $show_options = true; +foreach ($notes as $note) + include STAFFINC_DIR . 'templates/note.tmpl.php'; +?> +<div class="quicknote no-options" id="new-note" + data-url="users/<?php echo $user->getId(); ?>/note"> +<div class="body"> + <a href="#"><i class="icon-plus icon-large"></i> Click to create a new note</a> +</div> +</div> +</div> + </div> <div id="user-form" style="display:<?php echo $forms ? 'block' : 'none'; ?>;"> <div><p id="msg_info"><i class="icon-info-sign"></i> Please note that updates will be reflected system-wide.</p></div> diff --git a/include/staff/ticket-view.inc.php b/include/staff/ticket-view.inc.php index d155e040cfb7446f5c546cedc5a3cdee77b58e55..6c85c296f48cd02e251811a3325848b291e8c548 100644 --- a/include/staff/ticket-view.inc.php +++ b/include/staff/ticket-view.inc.php @@ -178,13 +178,17 @@ if($ticket->isOverdue()) <ul> <?php if(($open=$user->getNumOpenTickets())) - echo sprintf('<li><a href="tickets.php?a=search&status=open&uid=%s"><i class="icon-folder-open-alt"></i> %d Open Tickets</a></li>', + echo sprintf('<li><a href="tickets.php?a=search&status=open&uid=%s"><i class="icon-folder-open-alt icon-fixed-width"></i> %d Open Tickets</a></li>', $user->getId(), $open); if(($closed=$user->getNumClosedTickets())) - echo sprintf('<li><a href="tickets.php?a=search&status=closed&uid=%d"><i class="icon-folder-close-alt"></i> %d Closed Tickets</a></li>', + echo sprintf('<li><a href="tickets.php?a=search&status=closed&uid=%d"><i class="icon-folder-close-alt icon-fixed-width"></i> %d Closed Tickets</a></li>', $user->getId(), $closed); ?> - <li><a href="tickets.php?a=search&uid=<?php echo $ticket->getOwnerId(); ?>"><i class="icon-double-angle-right"></i> All Tickets</a></li> + <li><a href="tickets.php?a=search&uid=<?php echo $ticket->getOwnerId(); ?>"><i class="icon-double-angle-right icon-fixed-width"></i> All Tickets</a></li> + <li><a href="users.php?id=<?php echo $user->getId(); ?>" class="no-pjax"><i class="icon-user icon-fixed-width"></i> Manage Client</a></li> +<?php if ($user->getOrgId()) { ?> + <li><a href="orgs.php?id=<?php echo $user->getOrgId(); ?>" class="no-pjax"><i class="icon-building icon-fixed-width"></i> Manage Organization</a></li> +<?php } ?> </u> </div> <?php diff --git a/include/staff/user-view.inc.php b/include/staff/user-view.inc.php index 0e297150cbfce08f75add4395e6393f50ceeda50..4b267a9cc510d0bb4998ef34804bb1c885b014c4 100644 --- a/include/staff/user-view.inc.php +++ b/include/staff/user-view.inc.php @@ -119,13 +119,23 @@ $org = $user->getOrganization(); <ul class="tabs"> <li><a class="active" id="tickets_tab" href="#tickets"><i class="icon-list-alt"></i> User Tickets</a></li> + <li><a id="notes_tab" href="#notes"><i + class="icon-pushpin"></i> Notes</a></li> </ul> -<div id="tickets"> +<div id="tickets" class="tab_content"> <?php include STAFFINC_DIR . 'templates/tickets.tmpl.php'; ?> </div> +<div class="tab_content" id="notes" style="display:none"> +<?php +$notes = QuickNote::forUser($user); +$create_note_url = 'users/'.$user->getId().'/note'; +include STAFFINC_DIR . 'templates/notes.tmpl.php'; +?> +</div> + <div style="display:none;" class="dialog" id="confirm-action"> <h3>Please Confirm</h3> <a class="close" href=""><i class="icon-remove-circle"></i></a> diff --git a/js/redactor-osticket.js b/js/redactor-osticket.js index 0d4c202db9a824108eb46a91daaa2606bb132917..d93a9ee679cb707432559c472e0ee5bbc2360d02 100644 --- a/js/redactor-osticket.js +++ b/js/redactor-osticket.js @@ -206,9 +206,9 @@ $(function() { html = html.replace(/<inline /, '<span ').replace(/<\/inline>/, '</span>'); return html; }, - redact = function(el) { + redact = $.redact = function(el, options) { var el = $(el), - options = { + options = $.extend({ 'air': el.hasClass('no-bar'), 'airButtons': ['formatting', '|', 'bold', 'italic', 'underline', 'deleted', '|', 'unorderedlist', 'orderedlist', 'outdent', 'indent', '|', 'image'], 'buttons': ['html', '|', 'formatting', '|', 'bold', @@ -226,7 +226,7 @@ $(function() { 'tabFocus': false, 'toolbarFixedBox': true, 'focusCallback': function() { this.$box.addClass('no-pjax'); } - }; + }, options||{}); if (el.data('redactor')) return; var reset = $('input[type=reset]', el.closest('form')); if (reset) { diff --git a/scp/ajax.php b/scp/ajax.php index fada24ab53278dfda7acf32ab6c93c4afa59769d..2dd902087939a1c2f77240388d428ac3b6ad6878 100644 --- a/scp/ajax.php +++ b/scp/ajax.php @@ -90,7 +90,8 @@ $dispatcher = patterns('', url_post('^/(?P<id>\d+)/manage(?:/(?P<target>\w+))?$', 'manage'), url_get('^/(?P<id>\d+)/org(?:/(?P<orgid>\d+))?$', 'updateOrg'), url_post('^/(?P<id>\d+)/org$', 'updateOrg'), - url_get('^/staff$', 'searchStaff') + url_get('^/staff$', 'searchStaff'), + url_post('^/(?P<id>\d+)/note$', 'createNote') )), url('^/orgs', patterns('ajax.orgs.php:OrgsAjaxAPI', url_get('^$', 'search'), @@ -110,7 +111,8 @@ $dispatcher = patterns('', url_post('^/(?P<id>\d+)/add-user$', 'addUser'), url('^/(?P<id>\d+)/import-users$', 'importUsers'), url_get('^/(?P<id>\d+)/delete$', 'delete'), - url_delete('^/(?P<id>\d+)/delete$', 'delete') + url_delete('^/(?P<id>\d+)/delete$', 'delete'), + url_post('^/(?P<id>\d+)/note$', 'createNote') )), url('^/tickets/', patterns('ajax.tickets.php:TicketsAjaxAPI', url_get('^(?P<tid>\d+)/change-user$', 'changeUserForm'), @@ -144,6 +146,12 @@ $dispatcher = patterns('', url_post('^(?P<namespace>[\w.]+)$', 'createDraft'), url_get('^images/browse$', 'getFileList') )), + url('^/note/', patterns('ajax.note.php:NoteAjaxAPI', + url_get('^(?P<id>\d+)$', 'getNote'), + url_post('^(?P<id>\d+)$', 'updateNote'), + url_delete('^(?P<id>\d+)$', 'deleteNote'), + url_post('^attach/(?P<ext_id>\w\d+)$', 'createNote') + )), url_post('^/upgrader', array('ajax.upgrader.php:UpgraderAjaxAPI', 'upgrade')), url('^/help/', patterns('ajax.tips.php:HelpTipAjaxAPI', url_get('^tips/(?P<namespace>[\w_.]+)$', 'getTipsJson'), diff --git a/scp/css/scp.css b/scp/css/scp.css index 3e93fa84b4408b6511ff604f85e3869b1c25df2d..3d73c45cd2b5fbf3ec04d6dba2185b5104105589 100644 --- a/scp/css/scp.css +++ b/scp/css/scp.css @@ -1643,3 +1643,111 @@ tr.disabled th { opacity: 0.6; background: #f5f5f5; } + +.quicknote { + margin: 10px 0; + border: 1px solid rgba(0,0,0,0.2); + border-radius: 4px; +} +.quicknote .header { + position: relative; + display: block; + padding: 10px; + border-bottom: 1px dashed rgba(0,0,0,0.2); +} +.quicknote .header .header-left { + display: inline-block; +} +.quicknote .header .header-right { + display: inline-block; + text-align: right; + right: 1em; + position: absolute; +} +.quicknote .header .options { + display: inline-block; + padding-left: 10px; + margin-left: 5px; + white-space: nowrap; + border-left: 1px solid rgba(0,0,0,0.2); +} +.quicknote .body { + padding: 10px; +} +.quicknote a.action, +.floating-options a.action { + box-sizing: content-box; + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; + display: inline-block; + width: 15px; + text-align: center; + padding: 2px 2px; + color: black !important; + background-color: #eee; + background-color: rgba(0, 0, 0, 0.05); + border-width: 1px; + border-style: solid; + border-color: #ddd; + border-color: rgba(0, 0, 0, 0.1); + border-radius: 4px; +} +.quicknote a.action:hover, +.floating-options a.action:hover { + text-decoration: none; + border-color: #ff9100; + background-color: rgba(255, 145, 0, 0.05); + border-radius: 3px; +} +#new-note { + margin-top: 10px; +} + +.label { + font-size: 11px; + padding: 1px 4px 2px; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; + font-weight: bold; + line-height: 14px; + color: #ffffff; + vertical-align: baseline; + white-space: nowrap; + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); + background-color: #999999; +} +.label-info { + background-color: #3a87ad; +} + +.tab_content { + position: relative; +} +.floating-options { + display: inline-block; + position: absolute; + right: 0; + top: 5px; + padding-right: 5px; +} + +i.note-type { + color: #2a67ac; + opacity: 0.8; + border-right: 1px solid rgba(0, 0, 0, 0.2); + padding-right: 8px; +} + +table.custom-info th { + background: transparent; + border: none; + padding-top: 10px; + border-bottom: 1px dotted rgba(0,0,0,0.9); +} +table.custom-info tr { + vertical-align: top; +} +table.custom-info td { + border-bottom: 1px dotted rgba(0,0,0,0.3); +} diff --git a/scp/js/scp.js b/scp/js/scp.js index b93151a2fc317c8b08ddce39e7999e9b84f4b8d4..489cc72aecd056c9df19cf023d6fb3a9ec5dc1d5 100644 --- a/scp/js/scp.js +++ b/scp/js/scp.js @@ -662,3 +662,88 @@ $(document).on('click', 'a', function() { $(this).addClass('active'); } }); + +// Quick note interface +$('.quicknote .action.edit-note').live('click.note', function() { + var note = $(this).closest('.quicknote'), + body = note.find('.body'), + T = $('<textarea>').text(body.html()); + if (note.closest('.dialog').length) + T.addClass('no-bar small'); + body.replaceWith(T); + $.redact(T); + $(T).redactor('focus'); + note.find('.action.edit-note').hide(); + note.find('.action.save-note').show(); + note.find('.action.cancel-edit').show(); + return false; +}); +$('.quicknote .action.cancel-edit').live('click.note', function() { + var note = $(this).closest('.quicknote'), + T = note.find('textarea'), + body = $('<div class="body">'); + body.load('ajax.php/note/' + note.data('id'), function() { + try { T.redactor('destroy'); } catch (e) {} + T.replaceWith(body); + note.find('.action.save-note').hide(); + note.find('.action.cancel-edit').hide(); + note.find('.action.edit-note').show(); + }); + return false; +}); +$('.quicknote .action.save-note').live('click.note', function() { + var note = $(this).closest('.quicknote'), + T = note.find('textarea'); + $.post('ajax.php/note/' + note.data('id'), + { note: T.redactor('get') }, + function(html) { + var body = $('<div class="body">').html(html); + try { T.redactor('destroy'); } catch (e) {} + T.replaceWith(body); + note.find('.action.save-note').hide(); + note.find('.action.cancel-edit').hide(); + note.find('.action.edit-note').show(); + }, + 'html' + ); + return false; +}); +$('.quicknote .delete').live('click.note', function() { + var that = $(this), + id = $(this).closest('.quicknote').data('id'); + $.ajax('ajax.php/note/' + id, { + type: 'delete', + success: function() { + that.closest('.quicknote').animate( + {height: 0, opacity: 0}, 'slow', function() { + $(this).remove(); + }); + } + }); + return false; +}); +$('#new-note').live('click', function() { + var note = $(this).closest('.quicknote'), + top = note.parent(), + T = $('<textarea>'), + button = $('<input type="button">').val('Create'); + button.click(function() { + $.post('ajax.php/' + note.data('url'), + { note: T.redactor('get'), no_options: note.hasClass('no-options') }, + function(response) { + $(T).redactor('destroy').replaceWith(note); + $(response).show('highlight').insertBefore(note); + $('.submit', note.parent()).remove(); + }, + 'html' + ); + }); + if (note.closest('.dialog').length) + T.addClass('no-bar small'); + note.replaceWith(T); + $('<p>').addClass('submit').css('text-align', 'center') + .append(button).appendTo(T.parent()); + $.redact(T); + $(T).redactor('focus'); + return false; +}); diff --git a/scp/orgs.php b/scp/orgs.php index bfdc267aeacd56772f5226b49ec9f4c57e543e71..c48592ba7ec9db34543c8141975febf4d9f0f1f7 100644 --- a/scp/orgs.php +++ b/scp/orgs.php @@ -13,6 +13,8 @@ vim: expandtab sw=4 ts=4 sts=4: **********************************************************************/ require('staff.inc.php'); +require_once INCLUDE_DIR . 'class.note.php'; + $org = null; if ($_REQUEST['id'] || $_REQUEST['org_id']) $org = Organization::lookup($_REQUEST['org_id'] ?: $_REQUEST['id']); diff --git a/scp/users.php b/scp/users.php index 547d278ac52e5b3d91e7edd06c6602805d25b725..c8a483bab2968a115b112179010eeb374863a847 100644 --- a/scp/users.php +++ b/scp/users.php @@ -13,6 +13,9 @@ vim: expandtab sw=4 ts=4 sts=4: **********************************************************************/ require('staff.inc.php'); + +require_once INCLUDE_DIR.'class.note.php'; + $user = null; if ($_REQUEST['id'] && !($user=User::lookup($_REQUEST['id']))) $errors['err'] = 'Unknown or invalid user ID.';