Dan Wells [Thu, 16 Jan 2014 20:07:40 +0000 (15:07 -0500)]
Changes to smooth out make_release
1) Make the fake 'HeadURL' into a URL which works with our web repo.
Note that this has 'tags/' hardcoded in, so it only works with true
release branches (e.g. rel_x_y_z) not "working" branches
(e.g. rel_x_y).
2) Change range selector when building log to better exclude commits
from previous releases.
Docs: Fix filenames to match references in the docs
These image files were not displaying in the docs because the filenames
and the references used different capitalization. Web URLs are
case-sensitive, so this commit changes the image filenames to be all
lowercase.
Fall back to an unitialized maketext handler, which defaults to the
template language, when OpenILS::WWW::EGWeb::I18N->get_handle fails to
return a response.
Note that why get_handle() returns undef is not yet known.
Signed-off-by: Bill Erickson <berick@esilibrary.com> Signed-off-by: Ben Shum <bshum@biblio.org>
Jason Etheridge [Mon, 1 Oct 2012 20:49:04 +0000 (16:49 -0400)]
LP#1010027: tweak patron columns in patron search interface
specifically, remove the Mailing Address and Billing Address columns that come
off the actor table, since they are redundant with the Mailing Addr: Address ID
and Billing Addr: Address ID columns that come off the address table.
Also, alphabetize the columns coming directly off of the user table. The columns
coming off the library card and address tables remain unsorted; I believe their
order is as listed in the fm_IDL.xml file for their corresponding fieldmapper
definitions.
Signed-off-by: Jason Etheridge <jason@esilibrary.com> Signed-off-by: Jennifer Pringle <jpringle@sitka.bclibraries.ca> Signed-off-by: Ben Shum <bshum@biblio.org>
specifically, give fm_columns a sort_headers flag for alphabetizing the columns
returned by label; and delete_me flag for omitting a column definition entirely
Not all xul lists are using fm_columns yet
Signed-off-by: Jason Etheridge <jason@esilibrary.com> Signed-off-by: Jennifer Pringle <jpringle@sitka.bclibraries.ca> Signed-off-by: Ben Shum <bshum@biblio.org>
Chris Sharp [Tue, 11 Jun 2013 14:09:20 +0000 (10:09 -0400)]
LP#1189556: Fix typo in URL_VERIFY permission description
The description for the URL_VERIFY permission contained a typo,
fixed here.
Added an upgrade sql to update the text.
Signed-off-by: Chris Sharp <csharp@georgialibraries.org> Signed-off-by: Pasi Kallinen <pasi.kallinen@pttk.fi> Signed-off-by: Ben Shum <bshum@biblio.org>
Ben Shum [Wed, 30 Apr 2014 06:02:49 +0000 (02:02 -0400)]
LP#1314370: Enable dojo all the time in the catalog
Because we rely on the dojo framework for the shelving location filter in the
advanced search, we should choose to use dojo everywhere and not just when
autosuggest, google books, or novelist are enabled.
This is a quick change to toggle the flag for want_dojo to be set all the time.
Signed-off-by: Ben Shum <bshum@biblio.org> Signed-off-by: Liam Whalen <liam.whalen@bc.libraries.coop>
LP1277556 Fast Item Add no longer opens record after copy is created
Altered save_attempt to handle undefined and true cases for replace_on_complete
When fastItemAdd is not used, replace_on_complete is undefined
When it is used, and successful, replace_on_complete will be set to true
then we need it to execute result.on_complete()
Liam Whalen [Sat, 28 Jun 2014 22:37:28 +0000 (15:37 -0700)]
LP1084269, LP1050043 Expert Search Fixes
Sorting Expert Search corrected
LP1050043 was issued because attempting to sort the MARC expert search
results, in the staff client, caused the staff client to return to the
basic search page rather than sort the results.
To fix the sorting I had to modify two perl files.
metabib.pm had to be changed in a number of ways.
1. The way the sort works currently assumes the user is doing a full
text search. So, it passes in the values of titlesort and authorsort as
the sort variable in the URL. However, in the expert search, it is
looking for the values 'title' and 'author'. This resulted in the title
sort and author sort never being executed and returning the relevance
sort instead. I modified the search to use a regex instead of eq.
2. If a record has no value associated with it e.g. no 260 c for
pubdate, no 245 $a for title, no 1xx $a for author, then the SQL is
supposed to replace those values with either 'AAAA' or 'zzzz' depending
on the order of the sort. This should cause records without the
relevant sort values to be pushed to the bottom of the sort results.
But, the PgSQL function COALESCE, which is supposed to do the
replacing, does not do anything if no rows are returned for a record's
relevant value. To work around this, I surrounded the relevant values
with the MAX() function call, which returns NULL if no row is returned.
Because author sort works on any 1xx value, it sorts those values in
numerical order when there is more than one 1xx in a record. This
requires the use of an ORDER BY statement, which seems to nullify
the effect of MAX(). So, I had to move the MAX() into a second SELECT
statement in the case of author sort.
3. I added the variables number_default_sort and string_default_sort
to the metabib code because the current code hard codes values of
'9999' and 'zzzzzzzz' into the sort.
Search.pm had to be changed to pass the sort values from the TPAC
into the relevant sort subroutines. This was done with the addition of
an $arghash variable that checks the cgi parameters for the sort
variable.
As well, Expert search puts the tag and _special params in the
search form. This causes all other searches to perform Expert searches
afterwords. To fix this, Search.pm is modified to look for an empty
query value before it conducts an Expert search. If it is empty and
the Expert search variables are present, then the Expert search is
performed. Otherwise, a normal search is done.
Finally, to fix the problem reported by LP1050043, I had to modify
searchbar.tt2. Currently, searchbar.tt2 does not have the values from
the Expert search entered into the <form> where the sort functionality
is located. This means, when a sort option is chosen, the TPAC no
longer knows which values were used for the Expert search.
This is not obvious at first because after choosing to sort, the
user is returned to a page where the URL has the Expert search values
in it. This happens because the sort is submitting a form without a
query value, so the TPAC redirects the user to the referring page,
which is the initial Expert search.
To fix this, I added the Expert search values as hidden variables
into the <form> where the sort functionality is located. I also
removed the use of the "_adv" hidden variable from the <form> when
not in the advanced search.
[LP1094269] Retrive past 100 records in Expert Search
Currently, when paging through the results of the Expert search, the
system will not return more than 100 records. Going past page 10
causes a no results screen.
This is due to the offset and limit values not being passed into the
argument hash used to create the SQL for the search. Once the SQL
returns, it returns record ids within the range of the offset and
the limit. So, if the offset is 100 and the limit is 10, the record
ids for search results 100 to 109 are returned.
But, because offset and limit are not being passed into the arghash,
they default to 0 and 100 respectively. This means the first 100
records are always returned regardless of where in the search pages
you are viewing. These 100 results were then pruned to the relevant
10 results in Biblio.pm. However, if the offset starts beyond 100
then no results are returned because the results passed 100 are not
returned by metabib.pm.
This commit passes the offset and limit as arguments in the search
hash. It also removes offset and limit as parameters of the
search.biblio.marc call. Because offset and limit are needed in the
arghash to limit the number of records returned, it is better to
pass them only via the arghash to ensure that no more than the
necessary number of records are returned.
Offset and limit could be kept as parameters, but it would require
modifying metabib as well to look for those parameters, so I think
forcing the Expert search to pass them as argument parameters is the
better option.
As well, this commit removes the pruning in Biblio.pm that was based
on the offset and limit because that is handled in metabib.pm now
that offset and limit are being supplied in the argument hash.
I have checked the source code and the marc_search function in
Biblio.pm is only called via the Expert search in
WWW/EGCatLoader/Search.pm, so modifying Biblio.pm in this manner
will only affect the Expert search and nothing else.
Signed-off-by: Liam Whalen <liam.whalen@bc.libraries.coop> Signed-off-by: Sarah Childs <sarahc@zionsvillelibrary.org> Signed-off-by: Ben Shum <bshum@biblio.org>
Victoria Lewis [Wed, 30 Apr 2014 22:09:07 +0000 (15:09 -0700)]
lp1182605 Abstracting out common functionality from code that sorts call numbers by label_sortkey
Code had been added to insure that LC call numbers are sorting as they should by asset.call_number.label_sortkey.
Code was duplicated in the 'call_number column' in the 'columns' group and in the 'hold_columns'group.
I abstracted the logic out of 'sort_value' and 'render' in the 'call_number' column in the 'columns' group and from
'render' in the 'call_number' column in the 'hold_columns' group to a utility function called
'sort_call_numbers_by_label_sortkey'.
Signed-off-by: Victoria Lewis <vcamklewis@gmail.com>
modified: xul/staff_client/server/circ/util.js Signed-off-by: Kathy Lussier <klussier@masslnc.org> Signed-off-by: Remington Steed <rjs7@calvin.edu> Signed-off-by: Dan Wells <dbw2@calvin.edu>
Kyle Tomita [Mon, 2 Dec 2013 23:50:17 +0000 (15:50 -0800)]
LP1182605 : LC call numbers sort improperly in tabular displays
The issue was that the column was sorting on the label (call number)
and not label_sortkey. An attribute 'sort_value' was added that used
label_sortkey.
Dan Wells [Mon, 7 Jul 2014 17:16:58 +0000 (13:16 -0400)]
Fix currently harmless but still confusing sigil error
get_org_descendants() returns an array ref, not a list, so it doesn't
make sense to assign it to an '@orgs' variable. Lucky for us, our
where-parser treats this single element list containing the ref in the
same manner as the proper ref itself, but at best, it is still very
confusing to see.
Signed-off-by: Dan Wells <dbw2@calvin.edu> Signed-off-by: Kathy Lussier <klussier@masslnc.org>
If you have generated holdings, but are not using the "compressed"
display, your holdings show up regardless of scope. This change
limits the display to only sdists with a holding_lib in your current
search scope.
Signed-off-by: Dan Wells <dbw2@calvin.edu> Signed-off-by: Kathy Lussier <klussier@masslnc.org>
Bill Erickson [Tue, 25 Feb 2014 17:23:13 +0000 (12:23 -0500)]
LP#800478 repair logic error in acq fund transfer
The source data for the amount applied to each allocation and transfer
(in certain circumstances) was incorrect.
The transfer amount should not be the total amount allocated from the
source to the fund, but instead the amount of the funding source credit
in cases where we have to pull money from multiple funding source
credits.
Signed-off-by: Bill Erickson <berick@esilibrary.com> Signed-off-by: Liam Whalen <liam.whalen@bc.libraries.coop> Signed-off-by: Mike Rylander <mrylander@gmail.com>
Yamil Suarez [Thu, 7 Aug 2014 21:51:22 +0000 (17:51 -0400)]
Docs: various AsciiDoc formatting fixes for docs
Fixed the 'bad first character' error, the bad apostrophe error. Removed various UTF-8 chars.
Fixed some numbered list formatting, to take out redundant manual numerals…
for example:
. 1 item
. 2 item
. 3 item
became:
. item
. item
. item
also added "+" to wrap around breaks in numbered lists
for example:
. Right-click on the value control for the fixed field that needs to be edited.
image::media/ffrc1.jpg[]
. Select the appropriate value for the fixed field from the menu options.
became:
. Right-click on the value control for the fixed field that needs to be edited.
+
image::media/ffrc1.jpg[]
+
. Select the appropriate value for the fixed field from the menu options.
LP#1302207 - Attempt to validate ISBNs in AddedContent.pm.
When getting ISBNs from the database, they often contain extra stuff
after the ISBN that sometimes causes problems for Business::ISBN.
This commit attempts to resolve some of that by looking only for the
part of the ISBN data that resembles an ISBN and using just that part.
If the ISBN data doesn't look like an ISBN, then it is discarded.
Signed-off-by: Jason Stephenson <jstephenson@mvlc.org> Signed-off-by: Ben Shum <bshum@biblio.org>
Remington Steed [Wed, 6 Aug 2014 12:47:40 +0000 (08:47 -0400)]
Docs: Fix patron registration screenshot
The previously committed screenshot contains site-specific information
which is not broadly beneficial. This commit replaces it with a more
generic screenshot.
Remington Steed [Tue, 5 Aug 2014 15:23:20 +0000 (11:23 -0400)]
Docs: Update commands for authority importing script
The tools used for importing authority records from the command line have
been modified since the original docs were written. Testing revealed these
changes, which are reflected in this commit.
Mike Rylander [Fri, 20 Jun 2014 13:29:56 +0000 (09:29 -0400)]
LP#1322285: Exclude default values for fixed fields when ingesting
Default values for fixed fields that can exist in either 008 or 006
will cause search to be over-broad. So, we avoid including those now.
I also took the time to move the baseline schema around a bit in order
to keep related code in more appropriate files and avoid continuously
redefining functions.
Signed-off-by: Mike Rylander <mrylander@gmail.com> Signed-off-by: Jason Stephenson <jstephenson@mvlc.org>
Bill Erickson [Tue, 8 Oct 2013 19:52:12 +0000 (15:52 -0400)]
LP#1348731: Optional Auth login nonce to differentiate same-username logins
If multiple login attempts are made using the same username within a
very short period of time, a race condition exists where, upon
completion of the first login, the auth init cache data for any pending
logins are removed, since there can only be one instance of cached init
data per username.
This adds support for allowing the caller to pass in a random string
which is added to the cache key as a way to differentiate between logins
using the same username.
The seed is passed into auth init as an optional secondary parameter
and passed again (via the "nonce" argument) to auth complete to ensure
consistent cache keys across both interactions.
Example:
my $nonce = rand($$);
my $seed = request(
'open-ils.auth',
'open-ils.auth.authenticate.init', $username, $nonce );
Mike Rylander [Mon, 14 Jul 2014 18:57:38 +0000 (14:57 -0400)]
LP#1341703 Thinko in Batch Edit (hidden by older OpenSRFs)
There's a bug on line 272 of O::A::Cat.pm where we called a non-existent
method named respond_complete on the invocant object. Instead, we need to
call that on the client object (spelled $conn in this method). Batch bib
edit won't work on new OpenSRF's until this is fixed.
Signed-off-by: Mike Rylander <mrylander@gmail.com> Signed-off-by: Bill Erickson <berick@esilibrary.com>
This commit adds a note (with examples) about upgrading the database schema
across major versions. It also reformats a long line into multiple lines,
changes a NOTE to a TIP, makes a small correction, and replaces a repetitive
command with a short explanation.
Remington Steed [Fri, 6 Jun 2014 15:59:58 +0000 (11:59 -0400)]
LP#968514: Revive bib/auth importing docs from 2.1, add intro
This commit revives the following sections from the 2.1 version of the docs
and updates them for 2.6:
- marc_export: Exporting Bibliographic Records into MARC files
- includes new options for 2.6
- Importing Authority Records from Command Line
- Importing Authority Records from the Staff Client
The first two are included in a new section called "Support Scripts"
within the "Developer Resources" section, with a new intro and summary
of other commonly used scripts provided with Evergreen. The third section
is moved inside the Cataloging chapter "Batch Importing MARC Records",
with slight modifications to the intro to that chapter.
Documentation: Update upgrade instruction for 2.6.1
- Update location references for 2.6.1.
- Update database updates to include 2.6.1 update.
- Add a note regarding reingesting bib records after updates.
Signed-off-by: Robert Soulliere <robert.soulliere@mohawkcollege.ca>
Yamil Suarez [Mon, 30 Jun 2014 22:05:40 +0000 (18:05 -0400)]
Documentation: Added 'Using the OPAC' documentation & OPAC WCAG support mention
Older DocBook content that covered how to do searches on the OPAC was updated
to use Asciidoc. Also a simple mention of the 2.6 OPAC WCAG support was added.
Dan Scott [Wed, 4 Jun 2014 17:09:48 +0000 (13:09 -0400)]
LP#1326149 Use a TPAC-settable TIME_FORMAT for local time formats
We had tried to use the format.time library setting, but that is meant
for Dojo which uses the Unicode formats, that are incompatible with
the POSIX strftime() formats required by Template::Plugin::Date.
At the same time, we need to expose the raw machine-readable time
for schema.org consumers, so express that in a @content attribute.
And we might as well use a more meaningful <time> element instead of
the meaningless <span>, just for good measure.
Signed-off-by: Dan Scott <dscott@laurentian.ca> Signed-off-by: Ben Shum <bshum@biblio.org>
"If you can use a native HTML element [HTML5] or attribute with the
semantics and behaviour you require already built in, instead of
re-purposing an element and adding an ARIA role, state or property to
make it accessible, then do so."
Signed-off-by: Bill Erickson <berick@esilibrary.com> Signed-off-by: Ben Shum <bshum@biblio.org>
Instead of using titles / aria-labels directly on advanced search
selectors, provide selector IDs so the existing text labels can be
turned into <labels> and linked (by id) to their form control.
This means we only need one label per form control, which improves
usability from an accessibility perspective.
Bill Erickson [Wed, 2 Apr 2014 20:43:49 +0000 (16:43 -0400)]
LP#1301599 TPAC result table accessibility improvements
* Give the main result table a screenreader-only header to describe the
table columns.
* Set the role=presentation in one of the sub-tables used only for
layout.
Signed-off-by: Bill Erickson <berick@esilibrary.com> Signed-off-by: Ben Shum <bshum@biblio.org>
Mike Rylander [Fri, 2 May 2014 13:10:09 +0000 (09:10 -0400)]
LP#925776: Recheck located uri visibility
Previous to this commit, once we have determined that there are no
local Located URIs or foreign copies, we include the record in the
result set in the staff client. However, the desire of library staff
is that foreign Located URIs be valid as a visibility limiter. So
we now recheck at the end for that situation. This honors the new
"Located URIs act like copies" global flag.
Signed-off-by: Mike Rylander <mrylander@gmail.com> Signed-off-by: Ben Shum <bshum@biblio.org>
Galen Charlton [Thu, 5 Jun 2014 22:16:23 +0000 (15:16 -0700)]
LP#1326983: excluded fulfilled holds when adding hold_request.shelf_expires_soon events
This patch adjusts the example A/T filter for the
hold_request.shelf_expires_soon hook to exclude hold requests that are
already marked as fulfilled. This saves time creating events that
would immediately be marked as invalid per the HoldIsAvailable
validator.
It also addresses an issue for large databases that have lots of
fulfilled holds wherein hold_request.shelf_expires_soon events can
fail to be added at all due to a cstore timeout.
Signed-off-by: Galen Charlton <gmc@esilibrary.com> Signed-off-by: Ben Shum <bshum@biblio.org>
Galen Charlton [Tue, 20 May 2014 17:09:08 +0000 (10:09 -0700)]
LP#1296937: move the $force_bc parameter of ->charged_items() to an implementation method
Argubably, the $force_bc parameter of OpenILS::SIP::Patron->charged_items()
method exists solely as an implementation convenience for the renew-all
code. Consequently, this patch removes the $force_bc parameter from the
public interface for charged_items() and spins it off into a new
implementation method.
This patch should be applied at the same time that a reversion of
SIPServer commit c97d64412bc is applied. Note that a user who upgrades
SIPServer without upgrading Evergreen to a version that contains this
patch will end up in a situation where the code that counts active
loans for the patron information response will fetch the loans using
$force_bc set to true; this works only by coincidence.
Signed-off-by: Galen Charlton <gmc@esilibrary.com> Signed-off-by: Jeff Godin <jgodin@tadl.org>
Previously, in some cases (often needlessly) we ordered constituent
records within a metarecord by a combination of type/form/blvl. This
is not only of little use, but also expensive. Instead, order them
by the bib's calculated quality, which takes type/form/blvl into account
already.
Also, use the new metabib.record_sorter to find the title tie-breaker
instead of using the view-of-a-view-of-a-view mrd compatability shim.
The net result is several orders of magnitude speed increase for
constituent record retrieval. In particular, this resolves a problem
where doing a SIP2 patron information lookup and requesting a list
of holds could cause a timeout if the patron has one or more
metarecord holds.
This patch also causes the format filter parameter of the following
methods to be ignored:
Since the only use of the format filter was in JSPac code, and since
the record attributes mechanism has changed considerably, this removal
should be considered intentional.
Note that this patch includes a squash of a minor follow-up by Galen
Charlton to remove variables made unused by the original patch.
Signed-off-by: Mike Rylander <mrylander@gmail.com> Signed-off-by: Galen Charlton <gmc@esilibrary.com>
(for minor follow-up by Galen) Signed-off-by: Dan Wells <dbw2@calvin.edu>
Mike Rylander [Wed, 14 May 2014 15:54:47 +0000 (11:54 -0400)]
LP#1310751: Reorder query-building wrapper for QueryParser
In order to make sure that the transparent boolean pushdown does
not cause filters and modifiers to end up deeply embedded in the
query tree, we put them at the front.
This is a short-term fix. Long-term, we need to make use of the
floating subquery syntax ( {{ ... }} ) available in QueryParser,
which is designed to address the semantic separation between what
the user types into the search box, and the various UI widgets that
can add query clauses.
Signed-off-by: Jason Etheridge <jason@esilibrary.com> Signed-off-by: Dan Wells <dbw2@calvin.edu>
Bill Erickson [Thu, 22 May 2014 18:41:17 +0000 (14:41 -0400)]
LP#1322303 cleanse backdate for checkin overdue voiding
Passing raw backdates, particularly from offline transactions, which
have a space between the date and time, to
DateTime::Format::ISO8601->parse_datetime results in "Invalid date
format:" errors. Pass the date through the cleanse routine first.
Signed-off-by: Bill Erickson <berick@esilibrary.com> Signed-off-by: Ben Shum <bshum@biblio.org>
Remington Steed [Fri, 7 Mar 2014 18:56:25 +0000 (13:56 -0500)]
Remove buggy, unused function get_leaders_from_usergroup
Recent editing and testing of get_leaders_from_usergroup() uncovered an
unrelated bug which renders the function useless (it returns all group
members, not just the leader). It wasn't previously caught because
Evergreen has no apparent references to this function. This commit
removes the unused function.
Signed-off-by: Remington Steed <rjs7@calvin.edu> Signed-off-by: Dan Wells <dbw2@calvin.edu>
Galen Charlton [Tue, 20 May 2014 18:42:32 +0000 (11:42 -0700)]
LP#1321411: restore ability to handle credit payments using a processor other than Stripe
This patch ensures that the processor name is passed
to OpenILS::Application::Circ::CreditCard::process_payment, avoiding
an exception thrown by Business::OnlinePayment.
Signed-off-by: Galen Charlton <gmc@esilibrary.com> Signed-off-by: Dan Wells <dbw2@calvin.edu>
Jeff Godin [Wed, 30 Oct 2013 18:37:10 +0000 (14:37 -0400)]
LP#1246843: Don't show contact invalidators for new users
Don't show contact invalidator buttons for new users. This affects
staged users and cloned users, where the contact fields have a value
when the editor initially loads.
Signed-off-by: Jeff Godin <jgodin@tadl.org> Signed-off-by: Ben Shum <bshum@biblio.org>
When first calculating the shelf expire time, we assume "now" as
the starting point by calling DateTime->now(). However, that gives
us the time in UTC. That's not good because closed dates are stored
timezone-aware. Instead, ask for server-local time.
Signed-off-by: Mike Rylander <mrylander@gmail.com> Signed-off-by: Ben Shum <bshum@biblio.org>
Dan Wells [Thu, 1 May 2014 17:47:46 +0000 (13:47 -0400)]
LP#1314902: Restore header bar styles on results pages
Commit fc99f4f2 made an incomplete style change, changing
'results_header_bar' to be a class, but not changing the CSS. The
simplest solution is to restore 'results_header_bar' to be an id, as
this fixes the main view, the responsive view, and also any custom CSS
which might affect this id.
Srey Seng [Wed, 30 Apr 2014 22:20:17 +0000 (15:20 -0700)]
LP#1312945: authority.calculate_authority_linking and multiple linked tags
The function "authority.calculate_authority_linking" was not able to deal with
situations where there are multiple marc tags that are linkable. The function
only process the first tag that contains a linking_subfield and returns that
to be inserted into the authority_linking table, even when there are more than
one of the same tag with linking_subfield.
Added an additional loop to loop through each tag, for situations where there are
multiples of each tag.
Signed-off-by: Srey Seng <sreyseng@gmail.com> Signed-off-by: Mike Rylander <mrylander@gmail.com> Signed-off-by: Galen Charlton <gmc@esilibrary.com>
Mike Rylander [Wed, 30 Apr 2014 16:58:11 +0000 (12:58 -0400)]
LP#1312945: auth-auth linking: cache less agressively and look for all links
There was a logic inversion that was causing miss-use of a per-
record cache mechanism. I remove that entirely, as it's not helpful
in practice.
Also, after finding one use of a linked field we moved on to the
next, though it is possible for more than one link to exist for
different uses of a name, say. Now we'll loop through all fields
to find all possible linkages.
Signed-off-by: Mike Rylander <mrylander@gmail.com> Signed-off-by: Srey Seng <sreyseng@gmail.com> Signed-off-by: Galen Charlton <gmc@esilibrary.com>