Mailing List Archive

rt branch, 5.0/help-basics, updated. rt-5.0.1-451-g4f21360f23
The branch, 5.0/help-basics has been updated
via 4f21360f23360541a1c24185881862503e30afb0 (commit)
via 783f4ffa304cd7077309c636b28b185cb8d3420a (commit)
via 87a3ffe38bf790139b198c2564aba8c9a4a533db (commit)
via 9d21873df79c4e105afca2767365e5bfce687d36 (commit)
via aceb564affe64c585262e8fc0e493e880419ee58 (commit)
via 60afb5441f58043c97c3569a2d9176b9a6eba5cc (commit)
from b2dcd5b085a0cf813a33651b428d41469d959b10 (commit)

Summary of changes:
devel/docs/help-system.pod | 565 +++++++++++++++++++++++++++++++++++++++++
lib/RT/Interface/Web.pm | 1 -
share/html/Elements/PopupHelp | 46 ++++
share/html/Search/Results.html | 13 +-
4 files changed, 623 insertions(+), 2 deletions(-)
create mode 100644 devel/docs/help-system.pod

- Log -----------------------------------------------------------------
commit 9d21873df79c4e105afca2767365e5bfce687d36
Merge: b2dcd5b085 aceb564aff
Author: Steven Burr <steve@bestpractical.com>
Date: Mon Jun 14 10:21:36 2021 -0400

Merge branch '5.0-trunk' into 5.0/help-basics


commit 87a3ffe38bf790139b198c2564aba8c9a4a533db
Author: Steven Burr <steve@bestpractical.com>
Date: Thu Jun 17 09:00:50 2021 -0400

Add help system documentation

diff --git a/devel/docs/help-system.pod b/devel/docs/help-system.pod
new file mode 100644
index 0000000000..3837504f67
--- /dev/null
+++ b/devel/docs/help-system.pod
@@ -0,0 +1,565 @@
+=head1 OVERVIEW
+
+RT adds help icons to various elements on pages throughout the application.
+When the user clicks the help icon, a popup dialog will display useful information
+related to that element.
+
+The RT Help System can be used in a number of ways:
+
+=over
+
+=item *
+It is used internally by RT for help topics that ship with RT
+
+=item *
+It can be used to modify or augment the help topics that ship with RT
+
+=item *
+It can be used by extension authors to provide help for their extensions in a uniform fashion
+
+=back
+
+=head2 How it works
+
+Help content is managed as a collection of Articles in specially-designated Classes.
+If a Class has the special C<"RT Help System"> custom field set to C<"yes"> then that Articles
+in that Class are eligible to participate in the lookup of help topics. A second custom
+field called C<"Locale"> will identify the language used by Articles in that Class.
+
+When asked to display help for a particular topic, the RT help system will look for a
+Class that has been tagged as C<"RT Help System"> and has a C<"Locale"> compatible with the
+current user's language setting.
+
+Assuming it finds such a Class, RT will look inside it for an Article with a Name matching
+the help topic.
+
+=head2 Sync vs Async
+
+There are basically two modes of operation for the RT help system: synchronous and
+asynchronous.
+
+In synchronous mode, all of the help content is either retrieved or supplied directly on
+the server side when the initial page is rendered. This means that the help content itself
+is delivered to the browser.
+
+In asynchronous mode, only the help topic is supplied when the page is rendered. Only when
+the user clicks on the help icon is the help content dynamically retrieved from the server
+and displayed in the popup dialog. See L</Async> for more details.
+
+Both modes can be used interchangeably on the same page.
+
+=head1 USAGE
+
+The RT help system can be used at render time on the server. For example,
+in a Mason template, you might use the `PopupHelp` template to annotate a
+form field
+
+ <label for="ticketId">Ticket Id</label>
+ <& /Elements/PopupHelp, key => 'My Topic' &>
+ <input type="text" name="ticketId" />
+
+The RT help system can also be used at runtime on the client. For example,
+you can also add the same help topic to every HTML element matching a certain
+query. The following would associate a help topic to a specific button
+
+ <script>
+ jQuery(document).ready(function() {
+ addPopupHelpItems( [ { "selector": "button#save-form", "title": "My Topic" } ] )
+ })
+ </script>
+
+=head1 REFERENCE
+
+There are three primary ways to use the RT Help System:
+
+=over
+
+=item *
+L</Mason Templates>
+
+=item *
+L</HTML Attributes>
+
+=item *
+L</JavaScript>
+
+=back
+
+Of course, you are also free to use the lower-level contsructs as well.
+
+=over
+
+=item *
+L</Programmatic API>
+
+
+=back
+
+=head2 Mason Templates
+
+Add a C</Elements/PopupHelp> component anywhere in a Mason template
+
+ <& /Elements/PopupHelp, key => "My Topic" &>
+
+This will render an empty HTML span element
+
+ <span data-help="My Topic"
+ data-content="The article contents"
+ data-action="replace"
+ style="display: none;"
+ />
+
+which will be picked up and processed on page load by the default "helpification"
+rule when all of the accumulated rules are executed when C<renderPopupHelpItems> is
+called (for example, in the C<Elements/Footer> component in the page footer).
+
+If no valid help article named C<My Help Topic> is found, (see L</OVERVIEW>) or the
+C<ShowInlineHelp> setting/user-preference is falsy the C<<span>> will be suppressed
+altogether.
+
+Because the help content has already been retrieved and sent to the client,
+it will already be in the DOM and there should be virtually no delay when displaying
+the help popup following a user click.
+
+=head3 Example
+
+To add help to a form field, a Mason template might create a help tag directly,
+
+ <label for="ticketId">Ticket Id</label>
+ <& /Elements/PopupHelp, key => 'My Topic' &>
+ <input type="text" name="ticketId" />
+
+or might create help tags dynamically based on a Custom Field called Category
+
+ % while (my $ticket = $tickets->Next) {
+ % my $ctgy = $ticket->FirstCustomFieldValue("Category")
+ <h1><% $ticket->Subject %></h1><& /Elements/PopupHelp, $key => $ctgy &>
+ % }
+
+=head2 HTML Attributes
+
+Add C<data-help="My Topic"> and (optionally) C<data-content="The help content">
+attributes to any HTML elements.
+
+=over
+
+=item * C<data-help>
+Required. The name of the help topic. Used as the title of the popup dialog. If C<data-content>
+is omitted, content will come from an Article with this Name.
+
+=item * C<data-content>
+Optional. The help content. If omitted, asynchronous mode will be used to dynamically retrieve
+the help content. See L</Async>.
+
+=item * C<data-action>
+Optional. The action to use when adding the help icon to the DOM. Defaults to C<"append">. See
+L</Help Selector Rules> section for more details.
+
+=back
+
+=head3 Example
+
+A Mason template might add the C<data-help> attribute to an element along
+with some static help content that includes custom HTML
+
+ <button data-help="Save Widget"
+ data-content='Saves the <font color="red">Widget</font> to RT'
+ data-action="append">Save</button>
+
+Or we could omit the C<data-content> altogether to have RT return the help content from the
+matching C<"List Sprockets"> Article when the user clicks the help icon
+
+ <button data-help="List Sprockets" data-action="append">List</button>
+
+=head2 JavaScript
+
+Call C<addPopupHelpItems> to add one or more rules to the list of help topics on a page that
+should be decorated with help icons.
+
+The C<addPopupHelpItems> function populates the C<pagePopupHelpItems> array with a list of
+declarative rules that define elements in the DOM that should have associated help icons. If
+a rule's C<selector> key matches one or more elements, its C<action> key will
+determine where a help icon should be added to the DOM with help content corresponding to
+the C<content> key or from a valid help article with the same name as the C<title> key.
+
+Any rules thus added will be picked up and processed on page load when all of the accumulated
+rules are executed when C<renderPopupHelpItems> is called (for example, in the C<Elements/Footer>
+component in the page footer).
+
+This includes the default rule
+
+ { selector: "[data-help]", action: helpify }
+
+which matches anything with a C<data-help> attribute and therefore powers the L</HTML Attributes>
+method.
+
+This method of using JavaScript allows for tremendous flexibly annotating the DOM with help items,
+even after it has been rendered--perhaps by other templates altogether, making it attractive as a
+mechanism for customers to annotate aspects of RT--however it has been installed for them, including
+any and all extensions--simply by inspecting what is rendered to the browser and writing the
+appropriate rules. Importantly, these rules can usually be added to I<one place> (e.g. in a page
+callback somewhere) so they do I<not> need to overlay virtually every template in RT just to
+add help icons throughout.
+
+Note that C<renderPopupHelpItems> does not consider the C<ShowInlineHelp> setting/user-preference because
+it is assumed that the server-side logic would already have omitted the JavaScript call altogether
+(e.g. via the C</Elements/PopupHelp> component) if C<ShowInlineHelp> was unset.
+
+=head3 Help Selector Rules
+
+A help selector rule is a JavaScript object with the following keys
+
+=over
+
+=item * C<selector> - I<String | Function>
+
+Required. Defines which DOM elements should receive a help icon. Can match 0, 1, or many elements.
+Selectors matching 0 elements have no impact on the DOM.
+
+=over
+
+=item * I<String>
+A JQuery selector string that defines the matching DOM elements
+
+=item * I<Function>
+
+A JavaScript function that will be passed an instance of the C<JQuery> object and should
+return a JQuery collection of matching DOM elements. That is, the function signature
+is C<function( jQuery ) { ... }>
+
+=back
+
+=item * C<title> - I<String | Array(String) | Function>
+
+Optional. The help topic(s) that should be associated with the element(s) matching the C<selector>
+
+=over
+
+=item * I<String>
+The name of the help topic that should be matched against the Article Name. If the C<selector>
+matches exactly one element, this will be its help topic. If more than one element are
+matched, they will all get this same help topic.
+
+=item * I<Array(String)>
+An array of help topic names. They will be applied in order corresponding to the elements
+returned by the C<selector>
+
+=item * I<Function>
+A JavaScript function that will be called for each element matched by the C<selector> that
+should return the help topic for that element. That is, the function signagure is
+C<function( $el ) { ... }>
+
+=back
+
+=item * C<content> - I<String | Array(String)>
+
+Optional. The help content to be displayed in the popup when the user clicks the help icon.
+
+If missing, asynchronous mode is automatically triggered (see L</Async>)
+
+=over
+
+=item * I<String>
+The help content. May contain HTML. Will be applied for all elements matched by C<selector>.
+
+=item * I<Array(String)>
+Each member of the array will be applied to each corresponding member of the array of
+elements matched by C<selector>.
+
+=back
+
+=item * C<action> - I<String | Function>
+
+Optional. The action that should be taken with each help icon that results from the application
+of C<selector>. Responsible for actually adding the help icons to the DOM. This controls, for
+example, where the icon should be rendered relative to the matching DOM element.
+
+If missing, C<"replace"> is the default.
+
+=over
+
+=item * I<String>
+A shortcut method for referencing a number of predefined action functions. The following values
+are supported:
+
+=over
+
+=item * I<append>
+The help icon will be appended to the DOM I<after> the element(s) matched by C<selector>
+
+=item * I<prepend>
+The help icon will be prepended to the DOM I<before> the element(s) matched by C<selector>
+
+=item * I<replace>
+The help icon will be inserted into the DOM I<in place of> the element(s) matched by C<selector>.
+This is the default behavior. It is used, for example, by the C</Elements/PopupHelp> Mason component.
+
+=item * I<offset>
+The help icon will be offset from the element(s) matched by C<selector> by the amounts
+communicated in C<actionArgs>. Works with the JQuery C<offset> method and takes an object
+parameter with coordinate keys C<{ top: 10, left: 20 }>
+
+=back
+
+=item * I<Function>
+A JavaScript function responsible for actually adding the help icons to the DOM. Will be called
+for each element matched by the C<selector>. The function signature is C<function( $el, rule, actionArgs )>
+
+=back
+
+=item * C<actionArgs> - Array
+Any additional arguments that should be passed to the C<action> function.
+
+=back
+
+=head3 Examples
+
+Add a help topic named C<"My Topic"> to the DOM element with an id of C<"ticket-id">
+
+ addPopupHelpItems([.
+ {
+ selector: "#ticket-id",
+ title: "My Topic"
+ }
+ ])
+
+Add a help topic named C<"Phone"> and custom HTML content to the DOM element with an id of C<"phone-nbr">
+
+ addPopupHelpItems([.
+ {
+ selector: "#phone-nbr",
+ title: "Phone",
+ content: "The customer phone number. This <i>MUST</i> include the country code."
+ }
+ ])
+
+Add more than one rule at a time
+
+ addPopupHelpItems([.
+ { selector: "#ticket-status", title: "Status Topic" },
+ { selector: "#ticket-queue", title: "Queue Topic" }
+ ])
+
+Add a help topic named C<"A Note on Submitting Forms"> to every C<E<lt>buttonE<gt>> element
+of type C<submit>.
+
+ addPopupHelpItems([{ selector: "button[type='submit']", title: "A Note on Submitting Forms" }])
+
+Find every C<E<lt>divE<gt>> element with a C<"heading"> class, and add a help topic named
+C<"One"> to the first one, C<"Two"> to the second one, and C<"Three"> to the third one.
+
+ addPopupHelpItems([{ selector: "div.heading", title: [ "One", "Two", "Three" ]}])
+
+Use a custom C<selector> function to match divs that have ids starting with C<"ACME-"> but only when
+not working locally in developer mode. Determine the article title from the matching ids by stripping
+off the C<"ACME-"> portion
+
+ var acmeDivs = function( jQuery ) {
+ if (location.hostname != "localhost") {
+ return jQuery("div").filter(function($el) {
+ return $el.id.startsWith("ACME-")
+ })
+ }
+ }
+
+ var makeTitle = function( $el ) {
+ return $el.id.replace("ACME-", "")
+ }
+
+ addPopupHelpItems([.
+ {
+ selector: acmeDivs,
+ title: makeTitle
+ }
+ ])
+
+Prepend help topics to all form radio buttons
+
+ addPopupHelpItems([
+ {
+ selector: "form input[type='radio']",
+ topic: "Radio Button Help",
+ content: "You can only select one at a time",
+ action: "prepend"
+ }
+ ])
+
+Provide help for every field in each section on a ticket display page, but place each
+help icon in a line at the top of its respective section. Use asynchronous mode for
+help content, using the field text as the help topic.
+
+ var sectionInsert = function( $el, rule, options ) {
+ const $a = $el.closest(".titlebox").find(".titlebox-title.card-header a")
+ const fieldName = $el.text().replace(":", "")
+ $a.append( buildPopupHelpHtml( fieldName ) )
+ }
+
+ addPopupHelpItems([.
+ {
+ selector: ".titlebox .card-body .form-row .label",
+ action: sectionInsert
+ }
+ ])
+
+=head2 Programmatic API
+
+The following functions are part of, and used by, the RT Help System. You can also call them
+directly from your code.
+
+=head3 RT::Interface::Web::GetSystemHelpClass( locales )
+
+Given a list of locales, find the best article class that has been associated with the
+C<"RT Help System"> custom field. Locales are searched in order. The first Class with an
+C<"RT Help System"> custom field and matching C<"Locale"> custom field will be returned.
+
+=head3 RT::Interface::Web::GetHelpArticleContent( class_id, article_name )
+
+Returns the raw, unscrubbed and unescaped C<Content> of an Article of the given Class.
+Often, the class_id will come from C<GetSystemHelpClass>, but it does not have to.
+
+=head2 Async
+
+In asynchronous mode, only the help topic is supplied when the page is rendered. Only when
+the user clicks on the help icon is the help content dynamically retrieved from the server
+with a second AJAX request to which will attempt to fetch the given help article contents.
+The contents are returned directly as an HTML fragment--that is, they are not wrapped in
+a C<<html>> tag, for example.
+
+The AJAX call will be a request to C</Helpers/HelpTopic?key=MyTopic> which will return
+the raw contents of the C<MyTopic> Article, which may contain HTML. It will not be sanitized.
+If no valid C<MyTopic> help article exists (see L</OVERVIEW>),
+
+ <div class="text-danger">No help was found for 'MyTopic'.</div>
+
+will be returned instead.
+
+The C</Helpers/HelpTopic> component does not consider the C<ShowInlineHelp> setting/user-preference.
+However, if C<ShowInlineHelp> is not set, the help icon would generally not have been rendered
+anyway, so the AJAX call would never have been made.
+
+Asynchronous mode does have the benefit of reducing the number of database calls that need
+to be made to retrieve help article content on page request, but the user may experience a
+slight lag when the help icon is clicked and the AJAX request is being made. This will need
+to be evaluated on a case-by-case basis. On a heavily used RT system, the performance of pages
+with many help topics may benefit from using asynchronous mode more generously.
+
+=head1 NAMING
+
+Since the RT help system uses the help topic as the key to find a corresponding Article, it
+helps to have a somewhat predictable naming convention for help topics.
+
+=head2 RT objects
+
+In general, help topics for builtin RT functionality will be prefixed by C<"RT-">
+
+=over
+
+=item *
+RT-{The Name}
+
+=item *
+RT-{Context}-{The Name}
+
+=item *
+RT-{Path/To/Page}-{The Name}
+
+=item *
+RT-MainMenu-{}-{}-...
+
+=item *
+RT-PageMenu-{}-{}-...
+
+=back
+
+=head2 User-defined objects
+
+When you wish to dynamically create help topics based on the name of an object that the end
+users create, the following naming conventions can serve as a guide
+
+=over
+
+=item *
+User-Dashboard-{The Name}
+
+=item *
+System-Dashboard-{The Name}
+
+=item *
+CustomRole-{The Name}
+
+=item *
+SystemRole-{The Name}
+
+=item *
+CustomField-{The Name}
+
+=item *
+User-SavedSearch-{The Name}
+
+=item *
+{Group Name}-SavedSearch-{The Name}
+
+=item *
+System-SavedSearch-{The Name}
+
+=back
+
+=head1 DESIGN CONSIDERATIONS
+
+Choosing synchronous vs asynchronous mode involves several tradeoffs already discussed in
+L</Async>.
+
+In synchronous mode, there are also tradeoffs in choosing whether to provide content directly
+via the C<data-content> attribute or the C<content> property of a JavaScript help rule. It is
+often convenient to provide the help directly, especially if it has to be constructed in order
+to do so. However, this makes it much more difficult for end users to edit or customize the
+help content (since it now lives in code instead of an Article). It also makes it more
+difficult to support multiple locales.
+
+Help authors should choose the method that best balances these considerations for their
+use case.
+
+=head1 INTERNATIONALIZATION
+
+The RT help system works with multiple languages by using Articles in Classes. Each Class should
+have a different value for its C<Locale> Custom Field. All of the articles in that Class should
+be in that language.
+
+=head2 Adding a new language
+
+=over
+
+=item *
+Add a Class (for example, via B<Admin E<gt> Articles E<gt> Classes E<gt> Create>). You can name
+the Class whatever you want, but something like "Help - <language>" is probaby a good idea for clarity.
+
+=item *
+Associate it with the RT Help System. Find the "RT Help System" Custom Field (for example,
+B<Admin E<gt> Global E<gt> Custom Fields E<gt> Classes>) and apply it to your new Class
+
+=item *
+Associate it with a language. Find the "Locale" Custom Field (for example,
+B<Admin E<gt> Global E<gt> Custom Fields E<gt> Classes>) and apply it to your new Class
+
+=item *
+Set the language. Find your new Class (for example, B<Admin E<gt> Classes E<gt> Select>) and
+set the "Locale" to your <language> in the dropdown
+
+=item *
+Add articles to your new Class
+
+=back
+
+=head1 BUGS
+
+Please report them to rt-bugs@bestpractical.com, if you know what's
+broken and have at least some idea of what needs to be fixed.
+
+If you're not sure what's going on, start a discussion in the RT
+Developers category on the community forum at
+<https://forum.bestpractical.com> or send email to
+sales@bestpractical.com for professional assistance.
+
+=head1 SEE ALSO
+
+Devel

commit 783f4ffa304cd7077309c636b28b185cb8d3420a
Author: Steven Burr <steve@bestpractical.com>
Date: Fri Jun 18 08:38:57 2021 -0400

Remove debugging code

diff --git a/lib/RT/Interface/Web.pm b/lib/RT/Interface/Web.pm
index aad8e626e6..4501914c08 100644
--- a/lib/RT/Interface/Web.pm
+++ b/lib/RT/Interface/Web.pm
@@ -5233,7 +5233,6 @@ Often, the class_id will come from GetSystemHelpClass, but it does not have to.
=cut

sub GetHelpArticleContent {
- use Data::Printer;
my $class_id = shift || return ''; # required
my $article_name = shift || return ''; # required


commit 4f21360f23360541a1c24185881862503e30afb0
Author: Steven Burr <steve@bestpractical.com>
Date: Fri Jun 18 08:40:17 2021 -0400

Add BPS license

diff --git a/share/html/Elements/PopupHelp b/share/html/Elements/PopupHelp
index 874e5d08ff..7eae04d716 100644
--- a/share/html/Elements/PopupHelp
+++ b/share/html/Elements/PopupHelp
@@ -1,3 +1,49 @@
+%# BEGIN BPS TAGGED BLOCK {{{
+%#
+%# COPYRIGHT:
+%#
+%# This software is Copyright (c) 1996-2021 Best Practical Solutions, LLC
+%# <sales@bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
+%#
+%#
+%# LICENSE:
+%#
+%# This work is made available to you under the terms of Version 2 of
+%# the GNU General Public License. A copy of that license should have
+%# been provided with this software, but in any event can be snarfed
+%# from www.gnu.org.
+%#
+%# This work is distributed in the hope that it will be useful, but
+%# WITHOUT ANY WARRANTY; without even the implied warranty of
+%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+%# General Public License for more details.
+%#
+%# You should have received a copy of the GNU General Public License
+%# along with this program; if not, write to the Free Software
+%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+%# 02110-1301 or visit their web page on the internet at
+%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
+%#
+%#
+%# CONTRIBUTION SUBMISSION POLICY:
+%#
+%# (The following paragraph is not intended to limit the rights granted
+%# to you to modify and distribute this software under the terms of
+%# the GNU General Public License and is only of importance to you if
+%# you choose to contribute your changes and enhancements to the
+%# community by submitting them to Best Practical Solutions, LLC.)
+%#
+%# By intentionally submitting any modifications, corrections or
+%# derivatives to this work, or any other work intended for use with
+%# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+%# you are the copyright holder for those contributions and you grant
+%# Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
+%# royalty-free, perpetual, license to use, copy, create derivative
+%# works based on those contributions, and sublicense and distribute
+%# those contributions and any derivatives thereof.
+%#
<%args>
$key => ''
</%args>

-----------------------------------------------------------------------
_______________________________________________
rt-commit mailing list
rt-commit@lists.bestpractical.com
http://lists.bestpractical.com/cgi-bin/mailman/listinfo/rt-commit