Bugzilla – Attachment 152243 Details for
Bug 33961
In-built Offline circulation tool no longer working and should be removed
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 33961: Remove built-in offline circ tool
Bug-33961-Remove-built-in-offline-circ-tool.patch (text/plain), 76.99 KB, created by
Katrin Fischer
on 2023-06-09 11:57:50 UTC
(
hide
)
Description:
Bug 33961: Remove built-in offline circ tool
Filename:
MIME Type:
Creator:
Katrin Fischer
Created:
2023-06-09 11:57:50 UTC
Size:
76.99 KB
patch
obsolete
>From 781001874fb8fbdebe604d314be419b22b564702 Mon Sep 17 00:00:00 2001 >From: Jonathan Druart <jonathan.druart@bugs.koha-community.org> >Date: Thu, 8 Jun 2023 17:00:31 +0200 >Subject: [PATCH] Bug 33961: Remove built-in offline circ tool > >The tool has not been updated and is no longer working with modern >browser. > >It should either be rewritten/adjusted or removed. Given that we didn't >get complains its non-functional status, bugs related to this tool >didn't get attention, and the community is lacking resources, I am >suggesting to remove it and redirect users to the koct FF plugin that >is known to be working. > >Test plan: >See bug 10240 and use `git grep` to confirm that we are removing all >tracks of this feature. > >Signed-off-by: Owen Leonard <oleonard@myacpl.org> >Signed-off-by: Katrin Fischer <katrin.fischer.83@web.de> >--- > C4/UsageStats.pm | 1 - > circ/circulation-home.pl | 2 - > circ/offline-mf.pl | 35 - > circ/offline.pl | 39 - > .../data/mysql/atomicupdate/bug_33961.pl | 15 + > installer/data/mysql/mandatory/sysprefs.sql | 1 - > .../lib/jquery/plugins/jquery.indexeddb.js | 517 ------------ > .../prog/css/src/staff-global.scss | 25 - > .../admin/preferences/circulation.pref | 6 - > .../prog/en/modules/circ/circulation-home.tt | 3 - > .../prog/en/modules/circ/offline-mf.tt | 33 - > .../prog/en/modules/circ/offline.tt | 788 ------------------ > .../intranet-tmpl/prog/js/offlinecirc.js | 113 --- > offline_circ/download.pl | 108 --- > 14 files changed, 15 insertions(+), 1671 deletions(-) > delete mode 100755 circ/offline-mf.pl > delete mode 100755 circ/offline.pl > create mode 100755 installer/data/mysql/atomicupdate/bug_33961.pl > delete mode 100644 koha-tmpl/intranet-tmpl/lib/jquery/plugins/jquery.indexeddb.js > delete mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/circ/offline-mf.tt > delete mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/circ/offline.tt > delete mode 100644 koha-tmpl/intranet-tmpl/prog/js/offlinecirc.js > delete mode 100755 offline_circ/download.pl > >diff --git a/C4/UsageStats.pm b/C4/UsageStats.pm >index 89d45959c1..56877dd8af 100644 >--- a/C4/UsageStats.pm >+++ b/C4/UsageStats.pm >@@ -225,7 +225,6 @@ sub _shared_preferences { > SuspendHoldsOpac > TransferWhenCancelAllWaitingHolds > AllowAllMessageDeletion >- AllowOfflineCirculation > PatronAutoComplete > CircAutoPrintQuickSlip > DisplayClearScreenButton >diff --git a/circ/circulation-home.pl b/circ/circulation-home.pl >index 239051d850..e134907de4 100755 >--- a/circ/circulation-home.pl >+++ b/circ/circulation-home.pl >@@ -37,6 +37,4 @@ my ($template, $loggedinuser, $cookie, $flags) = get_template_and_user( > # Checking if there is a Fast Cataloging Framework > $template->param( fast_cataloging => 1 ) if Koha::BiblioFrameworks->find( 'FA' ); > >-$template->{'VARS'}->{'AllowOfflineCirculation'} = C4::Context->preference('AllowOfflineCirculation'); >- > output_html_with_http_headers $query, $cookie, $template->output; >diff --git a/circ/offline-mf.pl b/circ/offline-mf.pl >deleted file mode 100755 >index 19eb644f9e..0000000000 >--- a/circ/offline-mf.pl >+++ /dev/null >@@ -1,35 +0,0 @@ >-#!/usr/bin/perl >- >-# Copyright 2013 C & P Bibliography Services >-# This file is part of Koha. >-# >-# Koha is free software; you can redistribute it and/or modify it >-# under the terms of the GNU General Public License as published by >-# the Free Software Foundation; either version 3 of the License, or >-# (at your option) any later version. >-# >-# Koha 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 Koha; if not, see <http://www.gnu.org/licenses>. >- >-use Modern::Perl; >-use CGI qw ( -utf8 ); >-use C4::Auth qw( get_template_and_user ); >- >-my $query = CGI->new; >-my ( $template, $loggedinuser, $cookie, $flags ) = get_template_and_user( >- { >- template_name => "circ/offline-mf.tt", >- query => $query, >- type => "intranet", >- flagsrequired => { circulate => "circulate_remaining_permissions" }, >- } >-); >- >-$template->{'VARS'}->{'cookie'} = $cookie; >-print $query->header( -type => 'text/cache-manifest', cookie => $cookie ); >-print $template->output; >diff --git a/circ/offline.pl b/circ/offline.pl >deleted file mode 100755 >index 3843cb7243..0000000000 >--- a/circ/offline.pl >+++ /dev/null >@@ -1,39 +0,0 @@ >-#!/usr/bin/perl >- >-# Copyright 2013 C & P Bibliography Services >-# This file is part of Koha. >-# >-# Koha is free software; you can redistribute it and/or modify it >-# under the terms of the GNU General Public License as published by >-# the Free Software Foundation; either version 3 of the License, or >-# (at your option) any later version. >-# >-# Koha 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 Koha; if not, see <http://www.gnu.org/licenses>. >- >-use Modern::Perl; >-use CGI qw ( -utf8 ); >-use C4::Auth qw( get_template_and_user ); >-use C4::Output qw( output_html_with_http_headers ); >-use C4::Context; >- >-my $query = CGI->new; >-my ( $template, $loggedinuser, $cookie, $flags ) = get_template_and_user( >- { >- template_name => "circ/offline.tt", >- query => $query, >- type => "intranet", >- flagsrequired => { circulate => "circulate_remaining_permissions" }, >- } >-); >- >-$template->{'VARS'}->{'AllowOfflineCirculation'} = >- C4::Context->preference('AllowOfflineCirculation'); >-$template->{'VARS'}->{'maxoutstanding'} = >- C4::Context->preference('maxoutstanding') || 0; >-output_html_with_http_headers $query, $cookie, $template->output; >diff --git a/installer/data/mysql/atomicupdate/bug_33961.pl b/installer/data/mysql/atomicupdate/bug_33961.pl >new file mode 100755 >index 0000000000..9bc269a97d >--- /dev/null >+++ b/installer/data/mysql/atomicupdate/bug_33961.pl >@@ -0,0 +1,15 @@ >+use Modern::Perl; >+ >+return { >+ bug_number => "33961", >+ description => "Remove Offline circulation tool", >+ up => sub { >+ my ($args) = @_; >+ my ($dbh, $out) = @$args{qw(dbh out)}; >+ $dbh->do(q{ >+ DELETE FROM systempreferences >+ WHERE variable="AllowOfflineCirculation" >+ }); >+ say $out "Removed system preference 'AllowOfflineCirculation'"; >+ }, >+}; >diff --git a/installer/data/mysql/mandatory/sysprefs.sql b/installer/data/mysql/mandatory/sysprefs.sql >index db1dcabd01..1e7f15d170 100644 >--- a/installer/data/mysql/mandatory/sysprefs.sql >+++ b/installer/data/mysql/mandatory/sysprefs.sql >@@ -35,7 +35,6 @@ INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` > ('AllowMultipleCovers','0','1','Allow multiple cover images to be attached to each bibliographic record.','YesNo'), > ('AllowMultipleIssuesOnABiblio',1,'Allow/Don\'t allow patrons to check out multiple items from one biblio','','YesNo'), > ('AllowNotForLoanOverride','0','','If ON, Koha will allow the librarian to loan a not for loan item.','YesNo'), >-('AllowOfflineCirculation','0','','If on, enables HTML5 offline circulation functionality.','YesNo'), > ('AllowPatronToControlAutorenewal','0',NULL,'If enabled, patrons will have a field in their account to choose whether their checkouts are auto renewed or not','YesNo'), > ('AllowPatronToSetCheckoutsVisibilityForGuarantor', '0', NULL, 'If enabled, the patron can set checkouts to be visible to their guarantor', 'YesNo'), > ('AllowPatronToSetFinesVisibilityForGuarantor', '0', NULL, 'If enabled, the patron can set fines to be visible to their guarantor', 'YesNo'), >diff --git a/koha-tmpl/intranet-tmpl/lib/jquery/plugins/jquery.indexeddb.js b/koha-tmpl/intranet-tmpl/lib/jquery/plugins/jquery.indexeddb.js >deleted file mode 100644 >index e75a2a5875..0000000000 >--- a/koha-tmpl/intranet-tmpl/lib/jquery/plugins/jquery.indexeddb.js >+++ /dev/null >@@ -1,517 +0,0 @@ >-(function($, undefined) { >- var indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB; >- var IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange; >- var IDBCursor = window.IDBCursor || window.webkitIDBCursor; >- IDBCursor.PREV = IDBCursor.PREV || "prev"; >- IDBCursor.NEXT = IDBCursor.NEXT || "next"; >- >- /** >- * Best to use the constant IDBTransaction since older version support numeric types while the latest spec >- * supports strings >- */ >- var IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction; >- >- function getDefaultTransaction(mode) { >- var result = null; >- switch (mode) { >- case 0: >- case 1: >- case "readwrite": >- case "readonly": >- result = mode; >- break; >- default: >- result = IDBTransaction.READ_WRITE || "readwrite"; >- } >- return result; >- } >- >- $.extend({ >- /** >- * The IndexedDB object used to open databases >- * @param {Object} dbName - name of the database >- * @param {Object} config - version, onupgradeneeded, onversionchange, schema >- */ >- "indexedDB": function(dbName, config) { >- if (config) { >- // Parse the config argument >- if (typeof config === "number") config = { >- "version": config >- }; >- >- var version = config.version; >- if (config.schema && !version) { >- var max = -1; >- for (key in config.schema) { >- max = max > key ? max : key; >- } >- version = config.version || max; >- } >- } >- >- >- var wrap = { >- "request": function(req, args) { >- return $.Deferred(function(dfd) { >- try { >- var idbRequest = typeof req === "function" ? req(args) : req; >- idbRequest.onsuccess = function(e) { >- >- dfd.resolveWith(idbRequest, [idbRequest.result, e]); >- }; >- idbRequest.onerror = function(e) { >- >- dfd.rejectWith(idbRequest, [idbRequest.error, e]); >- }; >- if (typeof idbRequest.onblocked !== "undefined" && idbRequest.onblocked === null) { >- idbRequest.onblocked = function(e) { >- >- var res; >- try { >- res = idbRequest.result; >- } catch (e) { >- res = null; // Required for Older Chrome versions, accessing result causes error >- } >- dfd.notifyWith(idbRequest, [res, e]); >- }; >- } >- if (typeof idbRequest.onupgradeneeded !== "undefined" && idbRequest.onupgradeneeded === null) { >- idbRequest.onupgradeneeded = function(e) { >- >- dfd.notifyWith(idbRequest, [idbRequest.result, e]); >- }; >- } >- } catch (e) { >- e.name = "exception"; >- dfd.rejectWith(idbRequest, ["exception", e]); >- } >- }); >- }, >- // Wraps the IDBTransaction to return promises, and other dependent methods >- "transaction": function(idbTransaction) { >- return { >- "objectStore": function(storeName) { >- try { >- return wrap.objectStore(idbTransaction.objectStore(storeName)); >- } catch (e) { >- idbTransaction.readyState !== idbTransaction.DONE && idbTransaction.abort(); >- return wrap.objectStore(null); >- } >- }, >- "createObjectStore": function(storeName, storeParams) { >- try { >- return wrap.objectStore(idbTransaction.db.createObjectStore(storeName, storeParams)); >- } catch (e) { >- idbTransaction.readyState !== idbTransaction.DONE && idbTransaction.abort(); >- } >- }, >- "deleteObjectStore": function(storeName) { >- try { >- idbTransaction.db.deleteObjectStore(storeName); >- } catch (e) { >- idbTransaction.readyState !== idbTransaction.DONE && idbTransaction.abort(); >- } >- }, >- "abort": function() { >- idbTransaction.abort(); >- } >- }; >- }, >- "objectStore": function(idbObjectStore) { >- var result = {}; >- // Define CRUD operations >- var crudOps = ["add", "put", "get", "delete", "clear", "count"]; >- for (var i = 0; i < crudOps.length; i++) { >- result[crudOps[i]] = (function(op) { >- return function() { >- return wrap.request(function(args) { >- return idbObjectStore[op].apply(idbObjectStore, args); >- }, arguments); >- }; >- })(crudOps[i]); >- } >- >- result.each = function(callback, range, direction) { >- return wrap.cursor(function() { >- if (direction) { >- return idbObjectStore.openCursor(wrap.range(range), direction); >- } else { >- return idbObjectStore.openCursor(wrap.range(range)); >- } >- }, callback); >- }; >- >- result.index = function(name) { >- return wrap.index(function() { >- return idbObjectStore.index(name); >- }); >- }; >- >- result.createIndex = function(prop, options, indexName) { >- if (arguments.length === 2 && typeof options === "string") { >- indexName = arguments[1]; >- options = null; >- } >- if (!indexName) { >- indexName = prop; >- } >- return wrap.index(function() { >- return idbObjectStore.createIndex(indexName, prop, options); >- }); >- }; >- >- result.deleteIndex = function(indexName) { >- return idbObjectStore.deleteIndex(indexName); >- }; >- >- return result; >- }, >- >- "range": function(r) { >- if ($.isArray(r)) { >- if (r.length === 1) { >- return IDBKeyRange.only(r[0]); >- } else { >- return IDBKeyRange.bound(r[0], r[1], (typeof r[2] === 'undefined') ? true : r[2], (typeof r[3] === 'undefined') ? true : r[3]); >- } >- } else if (typeof r === "undefined") { >- return null; >- } else { >- return r; >- } >- }, >- >- "cursor": function(idbCursor, callback) { >- return $.Deferred(function(dfd) { >- try { >- >- var cursorReq = typeof idbCursor === "function" ? idbCursor() : idbCursor; >- cursorReq.onsuccess = function(e) { >- >- if (!cursorReq.result) { >- dfd.resolveWith(cursorReq, [null, e]); >- return; >- } >- var elem = { >- // Delete, update do not move >- "delete": function() { >- return wrap.request(function() { >- return cursorReq.result["delete"](); >- }); >- }, >- "update": function(data) { >- return wrap.request(function() { >- return cursorReq.result["update"](data); >- }); >- }, >- "next": function(key) { >- this.data = key; >- }, >- "key": cursorReq.result.key, >- "value": cursorReq.result.value >- }; >- >- dfd.notifyWith(cursorReq, [elem, e]); >- var result = callback.apply(cursorReq, [elem]); >- >- try { >- if (result === false) { >- dfd.resolveWith(cursorReq, [null, e]); >- } else if (typeof result === "number") { >- cursorReq.result["advance"].apply(cursorReq.result, [result]); >- } else { >- if (elem.data) cursorReq.result["continue"].apply(cursorReq.result, [elem.data]); >- else cursorReq.result["continue"](); >- } >- } catch (e) { >- >- dfd.rejectWith(cursorReq, [cursorReq.result, e]); >- } >- }; >- cursorReq.onerror = function(e) { >- >- dfd.rejectWith(cursorReq, [cursorReq.result, e]); >- }; >- } catch (e) { >- >- e.type = "exception"; >- dfd.rejectWith(cursorReq, [null, e]); >- } >- }); >- }, >- >- "index": function(index) { >- try { >- var idbIndex = (typeof index === "function" ? index() : index); >- } catch (e) { >- idbIndex = null; >- } >- >- return { >- "each": function(callback, range, direction) { >- return wrap.cursor(function() { >- if (direction) { >- return idbIndex.openCursor(wrap.range(range), direction); >- } else { >- return idbIndex.openCursor(wrap.range(range)); >- } >- >- }, callback); >- }, >- "eachKey": function(callback, range, direction) { >- return wrap.cursor(function() { >- if (direction) { >- return idbIndex.openKeyCursor(wrap.range(range), direction); >- } else { >- return idbIndex.openKeyCursor(wrap.range(range)); >- } >- }, callback); >- }, >- "get": function(key) { >- if (typeof idbIndex.get === "function") { >- return wrap.request(idbIndex.get(key)); >- } else { >- return idbIndex.openCursor(wrap.range(key)); >- } >- }, >- "count": function() { >- if (typeof idbIndex.count === "function") { >- return wrap.request(idbIndex.count()); >- } else { >- throw "Count not implemented for cursors"; >- } >- }, >- "getKey": function(key) { >- if (typeof idbIndex.getKey === "function") { >- return wrap.request(idbIndex.getKey(key)); >- } else { >- return idbIndex.openKeyCursor(wrap.range(key)); >- } >- } >- }; >- } >- }; >- >- >- // Start with opening the database >- var dbPromise = wrap.request(function() { >- >- return version ? indexedDB.open(dbName, parseInt(version)) : indexedDB.open(dbName); >- }); >- dbPromise.then(function(db, e) { >- >- db.onversionchange = function() { >- // Try to automatically close the database if there is a version change request >- if (!(config && config.onversionchange && config.onversionchange() !== false)) { >- db.close(); >- } >- }; >- }, function(error, e) { >- >- // Nothing much to do if an error occurs >- }, function(db, e) { >- if (e && e.type === "upgradeneeded") { >- if (config && config.schema) { >- // Assuming that version is always an integer >- >- for (var i = e.oldVersion + 1; i <= e.newVersion; i++) { >- typeof config.schema[i] === "function" && config.schema[i].call(this, wrap.transaction(this.transaction)); >- } >- } >- if (config && typeof config.upgrade === "function") { >- config.upgrade.call(this, wrap.transaction(this.transaction)); >- } >- } >- }); >- >- return $.extend(dbPromise, { >- "cmp": function(key1, key2) { >- return indexedDB.cmp(key1, key2); >- }, >- "deleteDatabase": function() { >- // Kinda looks ugly coz DB is opened before it needs to be deleted. >- // Blame it on the API >- return $.Deferred(function(dfd) { >- dbPromise.then(function(db, e) { >- db.close(); >- wrap.request(function() { >- return indexedDB.deleteDatabase(dbName); >- }).then(function(result, e) { >- dfd.resolveWith(this, [result, e]); >- }, function(error, e) { >- dfd.rejectWith(this, [error, e]); >- }, function(db, e) { >- dfd.notifyWith(this, [db, e]); >- }); >- }, function(error, e) { >- dfd.rejectWith(this, [error, e]); >- }, function(db, e) { >- dfd.notifyWith(this, [db, e]); >- }); >- }); >- }, >- "transaction": function(storeNames, mode) { >- !$.isArray(storeNames) && (storeNames = [storeNames]); >- mode = getDefaultTransaction(mode); >- return $.Deferred(function(dfd) { >- dbPromise.then(function(db, e) { >- var idbTransaction; >- try { >- >- idbTransaction = db.transaction(storeNames, mode); >- >- idbTransaction.onabort = idbTransaction.onerror = function(e) { >- dfd.rejectWith(idbTransaction, [e]); >- }; >- idbTransaction.oncomplete = function(e) { >- dfd.resolveWith(idbTransaction, [e]); >- }; >- } catch (e) { >- >- e.type = "exception"; >- dfd.rejectWith(this, [e]); >- return; >- } >- try { >- dfd.notifyWith(idbTransaction, [wrap.transaction(idbTransaction)]); >- } catch (e) { >- e.type = "exception"; >- dfd.rejectWith(this, [e]); >- } >- }, function(err, e) { >- dfd.rejectWith(this, [e, err]); >- }, function(res, e) { >- >- //dfd.notifyWith(this, ["", e]); >- }); >- >- }); >- }, >- "objectStore": function(storeName, mode) { >- var me = this, >- result = {}; >- >- function op(callback) { >- return $.Deferred(function(dfd) { >- function onTransactionProgress(trans, callback) { >- try { >- >- callback(trans.objectStore(storeName)).then(function(result, e) { >- dfd.resolveWith(this, [result, e]); >- }, function(err, e) { >- dfd.rejectWith(this, [err, e]); >- }); >- } catch (e) { >- >- e.name = "exception"; >- dfd.rejectWith(trans, [e, e]); >- } >- } >- me.transaction(storeName, getDefaultTransaction(mode)).then(function() { >- >- // Nothing to do when transaction is complete >- }, function(err, e) { >- // If transaction fails, CrudOp fails >- if (err.code === err.NOT_FOUND_ERR && (mode === true || typeof mode === "object")) { >- >- var db = this.result; >- db.close(); >- dbPromise = wrap.request(function() { >- >- return indexedDB.open(dbName, (parseInt(db.version, 10) || 1) + 1); >- }); >- dbPromise.then(function(db, e) { >- >- db.onversionchange = function() { >- // Try to automatically close the database if there is a version change request >- if (!(config && config.onversionchange && config.onversionchange() !== false)) { >- db.close(); >- } >- }; >- me.transaction(storeName, getDefaultTransaction(mode)).then(function() { >- >- // Nothing much to do >- }, function(err, e) { >- dfd.rejectWith(this, [err, e]); >- }, function(trans, e) { >- >- onTransactionProgress(trans, callback); >- }); >- }, function(err, e) { >- dfd.rejectWith(this, [err, e]); >- }, function(db, e) { >- if (e.type === "upgradeneeded") { >- try { >- >- db.createObjectStore(storeName, mode === true ? { >- "autoIncrement": true >- } : mode); >- >- } catch (ex) { >- >- dfd.rejectWith(this, [ex, e]); >- } >- } >- }); >- } else { >- dfd.rejectWith(this, [err, e]); >- } >- }, function(trans) { >- >- onTransactionProgress(trans, callback); >- }); >- }); >- } >- >- function crudOp(opName, args) { >- return op(function(wrappedObjectStore) { >- return wrappedObjectStore[opName].apply(wrappedObjectStore, args); >- }); >- } >- >- function indexOp(opName, indexName, args) { >- return op(function(wrappedObjectStore) { >- var index = wrappedObjectStore.index(indexName); >- return index[opName].apply(index[opName], args); >- }); >- } >- >- var crud = ["add", "delete", "get", "put", "clear", "count", "each"]; >- for (var i = 0; i < crud.length; i++) { >- result[crud[i]] = (function(op) { >- return function() { >- return crudOp(op, arguments); >- }; >- })(crud[i]); >- } >- >- result.index = function(indexName) { >- return { >- "each": function(callback, range, direction) { >- return indexOp("each", indexName, [callback, range, direction]); >- }, >- "eachKey": function(callback, range, direction) { >- return indexOp("eachKey", indexName, [callback, range, direction]); >- }, >- "get": function(key) { >- return indexOp("get", indexName, [key]); >- }, >- "count": function() { >- return indexOp("count", indexName, []); >- }, >- "getKey": function(key) { >- return indexOp("getKey", indexName, [key]); >- } >- }; >- }; >- >- return result; >- } >- }); >- } >- }); >- >- $.indexedDB.IDBCursor = IDBCursor; >- $.indexedDB.IDBTransaction = IDBTransaction; >- $.idb = $.indexedDB; >-})(jQuery); >\ No newline at end of file >diff --git a/koha-tmpl/intranet-tmpl/prog/css/src/staff-global.scss b/koha-tmpl/intranet-tmpl/prog/css/src/staff-global.scss >index 371ab2a772..b2e116b5a0 100644 >--- a/koha-tmpl/intranet-tmpl/prog/css/src/staff-global.scss >+++ b/koha-tmpl/intranet-tmpl/prog/css/src/staff-global.scss >@@ -3549,31 +3549,6 @@ span { > border-bottom-left-radius: 5px; > } > >-.loading-overlay { >- background-color: #FFFFFF; >- cursor: wait; >- height: 100%; >- left: 0; >- opacity: .7; >- position: fixed; >- top: 0; >- width: 100%; >- z-index: 1000; >- >- div { >- background: transparent url("../img/loading.gif") top left no-repeat; >- font-size: 175%; >- font-weight: bold; >- height: 2em; >- left: 50%; >- margin: -1em 0 0 -2.5em; >- padding-left: 50px; >- position: absolute; >- top: 50%; >- width: 15em; >- } >-} >- > #merge_invoices { > display: none; > margin: 1em auto; >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref >index c5308a8506..523d5279d5 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref >@@ -145,12 +145,6 @@ Circulation: > - "The following fields should be excluded from the patron checkout history CSV or MARC (ISO 2709) export:" > - pref: ExportRemoveFields > - (separate fields with space, e.g. 100a 200b 300c). >- - >- - pref: AllowOfflineCirculation >- choices: >- 1: Enable >- 0: "Don't enable" >- - "offline circulation on regular circulation computers. (<strong>NOTE:</strong> This system preference does not affect the Firefox add-on or the desktop application)." > - > - pref: ShowAllCheckins > choices: >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation-home.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation-home.tt >index 1c2c071bcb..b5ace5ebe9 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation-home.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation-home.tt >@@ -164,9 +164,6 @@ > <div class="col-md-12"> > <h4>Offline circulation</h4> > <div class="col-sm-5 col-md-3"> >- [% IF (AllowOfflineCirculation) %] >- <a href="/cgi-bin/koha/circ/offline.pl">Built-in offline circulation interface</a> >- [% END %] > <p><a href="/cgi-bin/koha/offline_circ/process_koc.pl">Upload offline circulation file (.koc)</a></p> > <p><a href="/cgi-bin/koha/offline_circ/list.pl">Pending offline circulation actions</a></p> > </div> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/offline-mf.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/offline-mf.tt >deleted file mode 100644 >index b937207c3c..0000000000 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/offline-mf.tt >+++ /dev/null >@@ -1,33 +0,0 @@ >-CACHE MANIFEST >-# [% cookie | html %] >- >-# Explicitly cached 'master entries'. >-CACHE: >-/cgi-bin/koha/circ/offline.pl >-[% interface | html %]/lib/bootstrap/bootstrap.min.css >-[% interface | html %]/lib/bootstrap/bootstrap-theme.min.css >-[% interface | html %]/lib/bootstrap/bootstrap.min.js >-[% interface | html %]/lib/jquery/jquery-ui-1.13.1.min.css >-[% interface | html %]/lib/jquery/jquery-ui-1.13.1.min.js >-[% interface | html %]/lib/jquery/jquery-3.6.0.min.js >-[% interface | html %]/lib/jquery/jquery-migrate-3.3.2.min.js >-[% interface | html %]/lib/jquery/plugins/jquery.highlight-3.js >-[% interface | html %]/lib/shortcut/shortcut.js >-[% interface | html %]/lib/jquery/plugins/jquery.indexeddb.js >-[% interface | html %]/lib/jquery/plugins/jquery.validate.min.js >-[% interface | html %]/[% theme | html %]/css/print.css >-[% interface | html %]/[% theme | html %]/css/staff-global.css >-[% interface | html %]/[% theme | html %]/js/basket.js >-[% interface | html %]/[% theme | html %]/js/offlinecirc.js >-[% interface | html %]/[% theme | html %]/js/staff-global.js >-[% interface | html %]/prog/img/koha-logo-medium.png >-[% interface | html %]/prog/img/loading.gif >-[% interface | html %]/prog/sound/beep.ogg >-[% interface | html %]/prog/sound/critical.ogg >- >-# Resources that require the user to be online. >-NETWORK: >-* >- >-# Resources that can be substituted if the user is offline >-FALLBACK: >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/offline.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/offline.tt >deleted file mode 100644 >index 5016d005c1..0000000000 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/offline.tt >+++ /dev/null >@@ -1,788 +0,0 @@ >-[% USE raw %] >-[% USE Asset %] >-[% USE Branches %] >-[% SET footerjs = 1 %] >-<!DOCTYPE html> >-[% IF (AllowOfflineCirculation) %] >-[% SET manifestattr = 'manifest="/cgi-bin/koha/circ/offline-mf.pl"' %] >-[% END %] >-[% IF ( bidi && AllowOfflineCirculation ) %]<html lang="[% lang | html %]" dir="[% bidi | html %]" manifest="/cgi-bin/koha/circ/offline-mf.pl"> >-[% ELSIF ( bidi ) %]<html lang="[% lang | html %]" dir="[% bidi | html %]"> >-[% ELSIF ( AllowOfflineCirculation ) %]<html lang="[% lang | html %]" manifest="/cgi-bin/koha/circ/offline-mf.pl"> >-[% ELSE %]<html lang="[% lang | html %]">[% END %] >-<head> >-<title>Circulation › Koha</title> >-[% INCLUDE 'doc-head-close.inc' %] >-</head> >- >-<body id="circ_offline" class="circ"> >-[% WRAPPER 'header.inc' %] >- [% INCLUDE 'circ-search.inc' %] >-[% END %] >-<div class="loading-overlay" style="display: none;"> >- <div>Downloading records, please wait...</div> >-</div> >- >-[% WRAPPER 'sub-header.inc' %] >- [% WRAPPER breadcrumbs %] >- [% WRAPPER breadcrumb_item %] >- <a id="go-to-home" href="#offline-home" aria-current="page">Offline circulation</a> >- [% END %] >- [% END #/ WRAPPER breadcrumbs %] >-[% END #/ WRAPPER sub-header.inc %] >- >-<div class="main container-fluid"> >- <div class="row"> >- <div class="col-sm-10 col-sm-push-2"> >- <main> >- <h1>Offline circulation</h1> >- >- <audio id="alert_sound" src="[% interface | html %]/prog/sound/critical.ogg" preload="auto"></audio> >- <audio id="success_sound" src="[% interface | html %]/prog/sound/beep.ogg" preload="auto"></audio> >- >- <div id="alerts"></div> >- >- [% UNLESS (AllowOfflineCirculation) %] >- <div id="noofflinecircwarning" class="dialog alert"> >- <p><strong>Warning:</strong> Offline circulation has been disabled. You may continue and record transactions, but patron and item information will not be available.</p> >- </div> >- [% END %] >- >- <div id="offline-home" class="offline-home"> >- <div class="row"> >- <div class="col-sm-6"> >- <ul> >- <li><a id="go-to-circ" href="#offline-circulation">Check out</a></li> >- <li><a id="go-to-returns" href="#offline-returns">Check in</a></li> >- </ul> >- </div> >- >- <div class="col-sm-6"> >- <p><strong>Note:</strong> You must be online to use these options.</p> >- <ul> >- <li><a id="go-to-sync" href="#offline-sync">Synchronize</a></li> >- <li><a id="go-to-pending" href="/cgi-bin/koha/offline_circ/list.pl">Pending offline circulation actions</a> >- </ul> >- </div> >- </div> >- </div> >- >- <div id="offline-sync" style="display: none;" class="offline-sync"> >- <div id="toolbar" class="btn-toolbar"> >- [% IF (AllowOfflineCirculation) %] >- <a href="#" id="download-records" class="btn btn-default"><i class="fa fa-arrow-down"></i> Download records</a> >- [% END %] >- <a href="#" id="upload-transactions" class="btn btn-default"><i class="fa fa-arrow-up"></i> Upload transactions</a> >- </div> >- <h1>Offline circulation</h1> >- <div class="row"> >- <div class="col-sm-6"> >- <div id="download-message"> >- In order for offline circulation to work on this computer, >- your library's records must be up-to-date on this computer: >- <ul> >- <li>Patron records were last synced on: <span id="patron-timestamp">(checking)</span></li> >- <li>Item records were last synced on: <span id="item-timestamp">(checking)</span></li> >- <li>Circulation records were last synced on: <span id="issue-timestamp">(checking)</span></li> >- </ul> >- </div> >- </div> >- >- <div class="col-sm-6"> >- <div id="upload-message"> >- </div> >- <div>View <a href="/cgi-bin/koha/offline_circ/list.pl">pending offline circulation actions</a></div> >- </div> >- </div> >- </div> >- >- <div id="offline-returns" style="display: none;" class="offline-returns"> >- <div class="row"> >- <form id="checkin-form" method="post" action="/cgi-bin/koha/circ/returns.pl" autocomplete="off" > >- <div class="col-sm-6"> >- <fieldset> >- <legend>Check in</legend> >- <label for="checkin-barcode">Enter item barcode: </label> >- <input name="barcode" id="checkin-barcode" size="14" class="focus" type="text" /> >- <input type="submit" class="btn btn-primary" value="Submit" /> >- </fieldset> >- </div> >- </form> >- </div> >- >- <div id="session-returned" style="display: none;"> >- <h2>Checked-in items</h2> >- <table id="already-checked-in"> >- <thead> >- <tr><th>Title</th><th>Author</th><th>Barcode</th><th>Home library</th><th>Holding library</th><th>Shelving location</th><th>Call number</th><th>Type</th></tr> >- </thead> >- <tbody> >- </tbody> >- </table> >- </div> >- </div> >- >- <div style="display: none;" class="offline-circulation-instructions"> >- Scan a patron barcode to start. >- </div> >- >- <div id="offline-circulation" style="display: none;" class="offline-circulation"> >- <form method="post" action="/cgi-bin/koha/circ/offline.pl" id="mainform" name="mainform" autocomplete="off"> >- <fieldset id="circ_circulation_issue"> >- <span id="clearscreen"><a href="/cgi-bin/koha/circ/offline.pl" title="Clear screen">x</a></span> >- <label for="checkout-barcode">Checking out to <span class="patron-title"></span></label> >- <div class="hint">Enter item barcode:</div> >- <input type="text" name="barcode" id="checkout-barcode" class="barcode focus" size="14" /> >- <input type="submit" class="btn btn-primary" value="Check out" /> >- >- <div class="date-select"> >- <div class="hint">Specify due date [% INCLUDE 'date-format.inc' %]: </div> >- <input type="text" size="13" id="duedatespec" name="duedatespec" value="[% duedatespec | html %]" class="flatpickr" data-flatpickr-enable-time="true" data-flatpickr-on-close-focus="#checkout-barcode" /> >- <label for="stickyduedate"> Remember for session:</label> >- <input type="checkbox" id="stickyduedate" onclick="this.form.barcode.focus();" name="stickyduedate" checked="checked" /> >- <input type="button" class="action" id="cleardate" value="Clear" name="cleardate" onclick="this.checked = false; this.form.duedatespec.value = ''; this.form.stickyduedate.checked = false; this.form.barcode.focus(); return false;" /> >- </div> >- </fieldset> >- </form> >- >- <div id="patronlists" class="toptabs"> >- <ul class="nav nav-tabs" role="tablist"> >- <li role="presentation" class="active"><a href="#checkouts" aria-controls="checkouts" role="tab" data-toggle="tab"><span class="checkout-count">0</span> Checkouts</a></li> >- <li role="presentation"><a href="#fines" aria-controls="fines" role="tab" data-toggle="tab"><span class="fine-amount">0</span> in fines</a></li> >- </ul> >- <div class="tab-content"> >- <!-- SUMMARY : TODAY & PREVIOUS ISSUES --> >- <div role="tabpanel" class="tab-pane active" id="checkouts"> >- <div id="session-issues"> >- <table id="issuest"> >- <thead><tr> >- <th scope="col">Due date</th> >- <th scope="col">Title</th> >- <th scope="col">Barcode</th> >- <th scope="col">Item type</th> >- <th scope="col">Checked out on</th> >- <th scope="col">Checked out from</th> >- <th scope="col">Call number</th> >- <th scope="col">Charge</th> >- </tr></thead> >- <tbody> >- </tbody> >- </table> >- </div> >- >- <div id="oldissues"> >- <h5>Previous checkouts</h5> >- <table id="oldissuest"> >- <thead><tr> >- <th scope="col">Due date</th> >- <th scope="col">Title</th> >- <th scope="col">Barcode</th> >- <th scope="col">Item type</th> >- <th scope="col">Checked out on</th> >- <th scope="col">Checked out from</th> >- <th scope="col">Call number</th> >- <th scope="col">Charge</th> >- </tr></thead> >- <tbody> >- </tbody> >- </table> >- </div> >- </div> >- >- <div role="tabpanel" class="tab-pane" id="fines"> >- <span class="patron-title"></span> has <span class="fine-amount">0</span> in fines. If you would like you can record payments. >- <fieldset><legend>Pay fines</legend> >- <label for="pay-fine-amount">Fine amount: </label><input type="text" name="pay-fine-amount" id="pay-fine-amount"/> >- <button id="pay-fine" class="submit">Pay fine</button> >- >- <table id="session-payments" style="display: none;"> >- <thead><tr><th>Amount</th><th>Date</th></tr></thead> >- <tbody></tbody> >- </table> >- </fieldset> >- </div> <!-- /# -->fines >- </div> <!-- /.tab-content --> >- </div> <!-- /#patronlists --> >- </div> >- </div> >- </main> >- >- </main> >- </div> <!-- /.col-sm-10.col-sm-push-2 --> >- >- <div class="offline-circulation" style="display: none;"> >- <div class="col-sm-2 col-sm-pull-10"> >- <aside> >- <div class="patroninfo"><h5 class="patron-title"> </h5> >- <ul> >- <li id="patron-address-1"></li> >- <li id="patron-address-2"></li> >- <li id="patron-address-parts"><!-- city, state, zipcode, country --></li> >- <li id="patron-phone"></li> >- <li id="patron-email"></li> >- <li id="patron-category"></li> >- <li id="patron-library"></li> >- </ul> >- </div> >- </aside> >- </div> <!-- /.col-sm-2.col-sm-pull-10 --> >- </div> <!-- /.row --> >- </div> >- >-[% MACRO jsinclude BLOCK %] >- [% INCLUDE 'calendar.inc' %] >- [% Asset.js("lib/jquery/plugins/jquery.indexeddb.js") | $raw %] >- [% Asset.js("js/offlinecirc.js") | $raw %] >- <script> >- var ALERT_SUCCESSFUL_CHECKIN = _("Checked in item."); >- var ALERT_MATERIALS = _("Note about the accompanying materials: %s"); >- var ALERT_RESTRICTED = _("Patron is RESTRICTED"); >- var ALERT_NO_MATCHING_ITEM = _("No item with barcode in offline database (transaction recorded anyway): %s"); >- var ALERT_NOT_CHECKED_OUT = _("Item not listed as checked out in offline database (transaction recorded anyway)"); >- var ALERT_ITEM_WITHDRAWN = _("Item has been withdrawn (transaction recorded anyway)"); >- var ALERT_ITEM_RESTRICTED = _("Item is restricted (transaction recorded anyway)"); >- var ALERT_ITEM_LOST = _("Item has been lost (transaction recorded anyway)"); >- var ALERT_NO_MATCHING_PATRON = _("No patron card number in offline database (proceeding anyway): %s"); >- var ALERT_PATRON_GONE_NO_ADDRESS = _("Patron's address is in doubt (proceeding anyway)"); >- var ALERT_PATRON_CARD_LOST = _("Patron's card is lost"); >- var ALERT_PATRON_EXPIRED = _("Patron's card is expired (%s)"); >- var ALERT_PATRON_BLOCKED_TEMPORARY = _("Patron has had overdue items and is restricted until: %s"); >- var ALERT_PATRON_RESTRICTED = _("Patron is restricted"); >- var ALERT_PATRON_FINE = _("Patron has outstanding fines: %s"); >- var ALERT_PATRON_FINE_OVER_LIMIT = _("Patron fines are over limit: %s"); >- var UPLOAD_PENDING_MESSAGE = _("You have transactions in the offline circulation database on this computer that have not been uploaded."); >- var NO_UPLOAD_PENDING_MESSAGE = _("You do not have any pending transactions in the offline circulation database on this computer."); >- >- var start; >- >- var dateformat = '[% IF ( dateformat_us ) %]mm/dd/yy[% ELSIF ( dateformat_metric ) %]dd/mm/yy[% ELSE %]yy-mm-dd[% END %]'; >- var flatpickr_dateformat_string = [% IF ( dateformat == "us" ) %]"m/d/Y"[% ELSIF ( dateformat == "metric" ) %]"d/m/Y"[% ELSIF ( dateformat == "dmydot" ) %]"d.m.Y"[% ELSE %]"Y-m-d"[% END %]; >- var flatpickr_timeformat_string = [% IF Koha.Preference('TimeFormat') == '12hr' %]"G:i K"[% ELSE %]"H:i"[% END %]; >- var flatpickr_timestamp_string = "Y-m-d H:i"; >- var flatpickr_datetime_string = flatpickr_dateformat_string + " " + flatpickr_timeformat_string; >- >- function checkin(barcode, item, error) { >- var alerts = checkAlerts(barcode, item); >- if (typeof item === 'undefined') { >- item = { }; >- } >- item.title = item.title || _("(Unknown)"); >- item.author = item.author || _("(Unknown)"); >- item.homebranch = item.homebranch || ""; >- item.holdingbranch = item.holdingbranch || ""; >- item.callnumber = item.callnumber || ""; >- item.itemtype = item.itemtype || ""; >- item.barcode = item.barcode || barcode; >- var trans = { "timestamp" : new Date().toMySQLString(), >- "barcode" : barcode, >- "action" : "return" >- }; >- $('#alerts').empty(); >- $('.offline-home').hide(); >- $('.offline-sync').hide(); >- $('.offline-circulation').hide(); >- $('.offline-circulation-instructions').hide(); >- $('.offline-returns').show(); >- kohadb.recordTransaction(trans, function () { >- $('#session-returned').show(); >- $('#already-checked-in tbody').prepend('<tr><td>' + item.title + '</td><td>' + item.author + '</td><td>' + barcode + '</td><td>' + item.homebranch + '</td><td>' + item.holdingbranch + '</td><td></td><td>' + item.callnumber + '</td><td>' + item.itemtype + '</td></tr>'); >- if (alerts.length > 0) { >- $('#alerts').append('<div class="dialog alert"><h3>' + _("Check in message") + '</h3></div>'); >- for (var msg in alerts) { >- $('#alerts .dialog').append('<p>' + alerts[msg] + '</p'); >- } >- } else { >- $('#alerts').append('<div class="dialog"><h3>' + ALERT_SUCCESSFUL_CHECKIN + '</h3></div>'); >- } >- }); >- setTimeout(function() { $('#checkin-barcode').trigger('focus'), 1 }); >- } >- >- function checkAlerts(barcode, item) { >- var alerts = []; >- if (typeof item === 'undefined') { >- alerts.push(ALERT_NO_MATCHING_ITEM.format(barcode)); >- } else { >- if (typeof item.materials !== 'undefined' && item.materials != null) { >- alerts.push(ALERT_MATERIALS.format(item.materials)); >- } >- } >- return alerts; >- } >- >- function showSyncInfo() { >- kohadb.loadSetting("item-timestamp", showTimestamp); >- kohadb.loadSetting("patron-timestamp", showTimestamp); >- kohadb.loadSetting("issue-timestamp", showTimestamp); >- kohadb.loadSetting("dirty", function (key, val) { >- if (val) { >- $('#upload-message').text(UPLOAD_PENDING_MESSAGE); >- } else { >- $('#upload-message').text(NO_UPLOAD_PENDING_MESSAGE); >- } >- }); >- } >- >- function synchronize() { >- kohadb.saveSetting("userid", "[% logged_in_user.userid | html %]"); >- kohadb.saveSetting("branchcode", "[% Branches.GetLoggedInBranchcode | html %]"); >- showSyncInfo(); >- [% UNLESS (AllowOfflineCirculation) %] >- reloadRecords(); >- [% END %] >- showSyncInfo(); >- $('#download-records').click(reloadRecords); >- $('#upload-transactions').click(function () { >- $('.loading-overlay div').text(_("Uploading transactions, please wait...")); >- $('.loading-overlay').show(); >- $.ajax({ >- type: "GET", >- url: "/cgi-bin/koha/offline_circ/service.pl", >- }).done(function (data) { >- if (data) { >- $('.loading-overlay').hide(); >- alert(_("Please log in to Koha and try again. (Error: '%s')").format(data)); >- } else { >- var uploadIter = $.indexedDB("koha").objectStore("transactions").each(uploadTransaction); >- uploadIter.done(function() { >- $.indexedDB("koha").transaction(["transactions"]).then(function(){ >- }, function(err, e){ >- }, function(transaction){ >- transaction.objectStore("transactions").clear(); >- }); >- $('.loading-overlay').hide(); >- kohadb.saveSetting("dirty", false); >- $('#upload-message').text(NO_UPLOAD_PENDING_MESSAGE); >- }); >- } >- }); >- }); >- >- } >- >- function fPformatTimeStamp( timestamp ){ >- var datetimeObj = flatpickr.parseDate( timestamp, flatpickr_timestamp_string ); >- return flatpickr.formatDate( datetimeObj, flatpickr_datetime_string ); >- } >- >- function showTimestamp(key, value) { >- if (typeof value !== 'undefined') { >- var ts = new Date(value); >- $('#' + key).text( fPformatTimeStamp( ts ) + ' ' + ts.toTimeString()); >- } else { >- $('#' + key).text(_("(never)")); >- } >- } >- >- function reloadRecords(ev) { >- $(".loading-overlay div").text(_("Loading records, please wait...")); >- $(".loading-overlay").show(); >- start = new Date(); >- $.indexedDB("koha").transaction(["patrons", "items", "issues"]).then(function(){ >- loadRecords(0); >- }, function(err, e){ >- }, function(transaction){ >- transaction.objectStore("patrons").clear(); >- transaction.objectStore("items").clear(); >- transaction.objectStore("issues").clear(); >- }); >- if (typeof ev !== 'undefined') { >- ev.stopPropagation(); >- } >- } >- >- function uploadTransaction(transaction) { >- $.ajax({ >- type: "POST", >- url: "/cgi-bin/koha/offline_circ/service.pl", >- data: { "userid" : kohadb.settings.userid, >- "branchcode" : kohadb.settings.branchcode, >- "timestamp" : transaction.value.timestamp, >- "action" : transaction.value.action, >- "barcode" : transaction.value.barcode, >- "cardnumber" : transaction.value.cardnumber, >- "amount" : transaction.value.amount, >- "pending" : true, >- }, >- }); >- return undefined, true; >- } >- >- function finishedLoading() { >- kohadb.saveSetting('item-timestamp', start.toISOString()) >- kohadb.saveSetting('patron-timestamp', start.toISOString()) >- kohadb.saveSetting('issue-timestamp', start.toISOString()) >- showTimestamp('item-timestamp', start.toISOString()); >- showTimestamp('patron-timestamp', start.toISOString()); >- showTimestamp('issue-timestamp', start.toISOString()); >- $(".loading-overlay").hide(); >- } >- >- function loadRecords(page) { >- [% IF (AllowOfflineCirculation) %] >- $(".loading-overlay div").text(_("Loading page %s, please wait...").format(page)); >- $(".loading-overlay").show(); >- $.ajax({ >- type: "GET", >- url: "/cgi-bin/koha/offline_circ/download.pl", >- data: { "data": "all", >- "page": page >- }, >- dataType: "json", >- }).done(function (data) { >- $.indexedDB("koha").transaction(["patrons", "items", "issues"]).then(function(){ >- if (data.finished) { >- finishedLoading(); >- } else { >- setTimeout(function () { loadRecords(page + 1); }, 200); >- } >- }, function(err, e){ >- }, function(transaction){ >- if (data.patrons) { >- var patrons = transaction.objectStore("patrons"); >- $.each(data.patrons, function () { >- patrons.put(this); >- }); >- } >- if (data.items) { >- var items = transaction.objectStore("items"); >- $.each(data.items, function () { >- items.put(this); >- }); >- } >- if (data.issues) { >- var issues = transaction.objectStore("issues"); >- $.each(data.issues, function () { >- issues.put(this); >- }); >- } >- }); >- }); >- [% END %] >- } >- >- function loadPatron(barcode) { >- $('#oldissues').hide(); >- $('#session-issues').hide(); >- $('#issuest tbody').empty(); >- $('#session-payments').hide(); >- $('.checkout-count').text(0); >- $.indexedDB("koha").transaction(["patrons", "issues"]).then(function() { >- }, function(err, e){ >- }, function(transaction){ >- var patrons = transaction.objectStore("patrons"); >- patrons.get(barcode).done(function (patron, error) { >- showPatron(barcode, patron, error); >- }); >- var issuesidx = transaction.objectStore("issues").index("cardnumber"); >- $('#oldissuest tbody').empty(); >- issuesidx.each(function (item) { >- $('#oldissues').show(); >- $('#oldissuest tbody').append("<tr><td>" + fPformatTimeStamp( item.value.date_due ) + "</td><td>" + item.value.title + "</td><td>" + item.value.barcode + "</td><td>" + item.value.itype + "</td><td>" + fPformatTimeStamp( item.value.issuedate ) + "</td><td>" + item.value.issuebranch + "</td><td>" + item.value.callnumber + "</td><td>" + "" + "</td></tr>"); >- $('.checkout-count').text(parseInt($('.checkout-count').text()) + 1); >- }, barcode); >- }); >- } >- >- function checkout(barcode, item, error) { >- var alerts = checkAlerts(barcode, item); >- if (typeof item === 'undefined') { >- item = { }; >- } >- item.title = item.title || ""; >- item.author = item.author || ""; >- item.homebranch = item.homebranch || ""; >- item.holdingbranch = item.holdingbranch || ""; >- item.callnumber = item.callnumber || ""; >- item.itemtype = item.itemtype || ""; >- if ($('#duedatespec').val().length === 0) { >- alert(_("You must set a due date in order to use offline circulation!")); >- setTimeout(function() { $('#duedatespec').trigger('focus'), 1 }); >- return; >- } >- var date_due = flatpickr.parseDate( $('#duedatespec').val(), flatpickr_datetime_string ); >- var trans = { "timestamp" : new Date().toMySQLString(), >- "barcode" : barcode, >- "cardnumber" : curpatron.cardnumber, >- "date_due" : date_due.toMySQLString(), >- "action" : "issue" >- }; >- $('#alerts').empty(); >- kohadb.recordTransaction(trans, function () { >- $('#session-issues').show(); >- $('#issuest tbody').prepend('<tr><td>' + flatpickr.formatDate( date_due, flatpickr_datetime_string ) + '</td><td>' + item.title + '</td><td>' + barcode + '</td><td>' + item.itemtype + '</td><td>' + flatpickr.formatDate( new Date(), flatpickr_datetime_string ) + '</td><td>' + kohadb.settings.branchcode + '</td><td>' + item.callnumber + '</td><td></td></tr>'); >- $('.checkout-count').text(parseInt($('.checkout-count').text()) + 1); >- if (alerts.length > 0) { >- $('#alerts').append('<div class="dialog alert"><h3>' + _("Check out message") + '</h3></div>'); >- for (var msg in alerts) { >- $('#alerts .dialog').append('<p>' + alerts[msg] + '</p'); >- } >- } >- $('#checkout-barcode').val(''); >- }); >- } >- >- function recordFine(amount) { >- var timestamp = new Date() >- var trans = { "timestamp" : timestamp.toMySQLString(), >- "cardnumber" : curpatron.cardnumber, >- "amount" : amount, >- "action" : "payment", >- }; >- kohadb.recordTransaction(trans, function () { >- $('#session-payments').show(); >- $('#session-payments tbody').prepend('<tr><td>' + amount + '</td><td>' + fPformatTimeStamp( timestamp ) + '</td></tr>'); >- $('.fine-amount').text(parseInt($('.fine-amount').text()) - amount); >- }); >- } >- >- function checkPatronAlerts(cardnumber, patron) { >- var alerts = []; >- if (typeof patron === 'undefined') { >- alerts.push(ALERT_NO_MATCHING_PATRON.format(cardnumber)); >- } else { >- if (patron.gonenoaddress !== '0') { >- alerts.push(ALERT_PATRON_GONE_NO_ADDRESS); >- } >- if (patron.lost !== '0') { >- alerts.push(ALERT_PATRON_CARD_LOST); >- } >- if (patron.debarred !== null) { >- if (patron.debarred != '9999-12-31') { >- alerts.push( ALERT_PATRON_BLOCKED_TEMPORARY.format( flatpickr.formatDate( new Date(patron.debarred), flatpickr_datetime_string ) ) ); >- } else { >- alerts.push(ALERT_PATRON_RESTRICTED); >- } >- } >- if (new Date(patron.dateexpiry) < new Date()) { >- alerts.push( ALERT_PATRON_EXPIRED.format( flatpickr.formatDate( new Date(patron.dateexpiry), flatpickr_datetime_string ) ) ); >- } >- if (parseInt(patron.fine) > [% maxoutstanding | html %]) { >- alerts.push(ALERT_PATRON_FINE_OVER_LIMIT.format(patron.fine)); >- } else if (parseInt(patron.fine) > 0) { >- alerts.push(ALERT_PATRON_FINE.format(patron.fine)); >- } >- } >- return alerts; >- } >- >- var curpatron; >- >- function showPatron(barcode, patron, error) { >- var alerts = checkPatronAlerts(barcode, patron); >- if (typeof patron === 'undefined') { >- patron = { }; >- } >- patron.surname = patron.surname || ""; >- patron.firstname = patron.firstname || ""; >- patron.othernames = patron.othernames || ""; >- patron.address = patron.address || ""; >- patron.address2 = patron.address2 || ""; >- patron.city = patron.city || ""; >- patron.state = patron.state || ""; >- patron.country = patron.country || ""; >- patron.zipcode = patron.zipcode || ""; >- patron.phone = patron.phone || ""; >- patron.mobile = patron.mobile || ""; >- patron.phonepro = patron.phonepro || ""; >- patron.email = patron.email || ""; >- patron.emailpro = patron.emailpro || ""; >- patron.categorycode = patron.categorycode || ""; >- patron.branchcode = patron.branchcode || ""; >- patron.cardnumber = barcode; >- patron.fine = patron.fine || "0"; >- >- patron.name = patron.firstname + (patron.othernames.length > 0 ? " (" + patron.othernames + ") " : " ") + patron.surname + " (" + barcode + ")"; >- if (patron.name.length > 0) { >- $('.patron-title').text(patron.name); >- } else { >- $('.patron-title').text(_("Unrecognized patron (%s)").format(barcode)); >- } >- if (patron.address.length > 0 || patron.address2.length > 0) { >- $('#patron-address-1').text(patron.address); >- $('#patron-address-2').text(patron.address2); >- } else { >- $('#patron-address-1').html('<span class="empty" id="noaddressstored">' + _("No address stored.") + '</span></li>'); >- $('#patron-address-2').text(''); >- } >- if (patron.city.length > 0) { >- $('#patron-address-parts').text(patron.city + (patron.state.length > 0 ? ", " + patron.state : "") + " " + patron.zipcode + (patron.country.length > 0 ? ", " + patron.country : "")); >- } else { >- $('#patron-address-parts').html('<span class="empty" id="nocitystored">' + _("No city stored.") + '</span></li>'); >- } >- if (patron.phone.length > 0 || patron.mobile.length > 0 || patron.phonepro.length > 0) { >- $('#patron-phone').text((patron.phone.length > 0 ? patron.phone : (patron.mobile.length > 0 ? patron.mobile : (patron.phonepro.length > 0 ? patron.phonepro : '')))); >- } else { >- $('#patron-phone').html('<span class="empty" id="nophonestored">' + _("No phone stored.") + '</span></li>'); >- } >- if (patron.email.length > 0 || patron.emailpro.length > 0) { >- $('#patron-email').text((patron.email.length > 0 ? patron.email : (patron.emailpro.length > 0 ? patron.emailpro : ""))); >- } else { >- $('#patron-email').html('<span class="empty" id="noemailstored">' + _("No email stored.") + '</span></li>'); >- } >- if (patron.categorycode.length > 0) { >- $('#patron-category').text(_("Category: %s").format(patron.categorycode)); >- } else { >- $('#patron-category').html('<span class="empty" id="unknowncategory">' + _("Category code unknown.") + '</span></li>'); >- } >- if (patron.branchcode.length > 0) { >- $('#patron-library').text(_("Home library: %s").format(patron.branchcode)); >- } else { >- $('#patron-library').html('<span class="empty" id="unknowncategory">' + _("Home library unknown.") + '</span></li>'); >- } >- $('.fine-amount').text(patron.fine); >- $('#alerts').empty(); >- if (alerts.length > 0) { >- $('#alerts').append('<div class="dialog alert"><h3>' + _("Check out message") + '</h3></div>'); >- for (var msg in alerts) { >- $('#alerts .dialog').append('<p>' + alerts[msg] + '</p>'); >- } >- } >- curpatron = patron; >- $('main').show(); >- setTimeout(function() { $('#checkout-barcode').trigger('focus'), 1 }); >- } >- >- // This next bit of code is to deal with the updated session issue >- if( typeof window.applicationCache !== "undefined" ){ >- window.addEventListener('load', function(e) { >- window.applicationCache.addEventListener('updateready', function(e) { >- if (window.applicationCache.status == window.applicationCache.UPDATEREADY) { >- // Browser downloaded a new app cache. >- // Swap it in and reload the page to get the new hotness. >- window.applicationCache.swapCache(); >- if (confirm(_("A new version of this site is available. Load it?"))) { >- window.location.reload(); >- } >- } else { >- // Manifest didn't changed. Nothing new to server. >- } >- }, false); >- }, false); >- } >- >- >- $(document).ready(function () { >- if( typeof window.applicationCache === "undefined" ){ >- $("#offline-home div").html('<div class="dialog alert"><h3>' + _("Offline circulation disabled") + '</h3><p>' + _("Your browser is not compatible with the built-in offline circulation tool.") + '</div>'); >- } else { >- kohadb.initialize(); >- } >- $('#header_search #circ_search .tip').text(_("Enter patron card number:")); >- >- $('ul[aria-labelledby="logged-in-menu"]').html('<li><a class="toplinks">' + _("You cannot change your branch or logout while using offline circulation") + '</a></li>'); >- >- // Returns code >- $('#checkin-form, #checkin_search form').submit(function (event) { >- event.preventDefault(); >- var barcode = $('input[name="barcode"]', this).val(); >- $('input[name="barcode"]', this).val(''); >- $.indexedDB("koha").transaction(["items"]).then(function() { >- }, function(err, e){ >- }, function(transaction){ >- var items = transaction.objectStore("items"); >- items.get(barcode).done(function (item, error) { >- checkin(barcode, item, error); >- }); >- }); >- }); >- >- $('#go-to-home').click(function () { >- $('#alerts').empty(); >- $('.offline-sync').hide(); >- $('.offline-circulation').hide(); >- $('.offline-returns').hide(); >- $('.offline-circulation-instructions').hide(); >- $('.offline-home').show(); >- }); >- >- $('#go-to-returns').click(function () { >- $('#alerts').empty(); >- $('.offline-home').hide(); >- $('.offline-sync').hide(); >- $('.offline-circulation').hide(); >- $('.offline-circulation-instructions').hide(); >- $('.offline-returns').show(); >- setTimeout(function() { $('#checkin-form input[name="barcode"]').trigger('focus'), 1 }); >- }); >- >- $('#go-to-circ').click(function () { >- $('#alerts').empty(); >- $('.offline-home').hide(); >- $('.offline-sync').hide(); >- $('.offline-returns').hide(); >- $('.offline-circulation').hide(); >- $('.offline-circulation-instructions').show(); >- $('#header_search').selectTabByID("#circ_search"); >- setTimeout(function() { $('#circ_search input[name="findborrower"]').trigger('focus'), 1 }); >- }); >- >- $('#go-to-sync').click(function () { >- $('#alerts').empty(); >- showSyncInfo(); >- $.ajax({ >- type: "GET", >- url: "/cgi-bin/koha/offline_circ/list.pl", >- success: function () { >- $('.offline-home').hide(); >- $('.offline-returns').hide(); >- $('.offline-circulation').hide(); >- $('.offline-circulation-instructions').hide(); >- $('.offline-sync').show(); >- synchronize(); >- }, >- error: function () { >- alert(_("You are offline and therefore cannot sync your database")); >- } >- }); >- }); >- >- $('#go-to-pending').click(function (ev) { >- $('#alerts').empty(); >- ev.preventDefault(); >- $.ajax({ >- type: "GET", >- url: "/cgi-bin/koha/offline_circ/list.pl", >- success: function () { >- window.location = '/cgi-bin/koha/offline_circ/list.pl'; >- }, >- error: function () { >- alert(_("You are offline and therefore cannot process pending operations")); >- } >- }); >- }); >- >- $('#patronsearch').submit(function (event) { >- event.preventDefault(); >- loadPatron($('#findborrower').val()); >- $('.offline-home').hide(); >- $('.offline-returns').hide(); >- $('.offline-sync').hide(); >- $('.offline-circulation-instructions').hide(); >- $('.offline-circulation').show(); >- $('#findborrower').val(''); >- setTimeout(function() { $('#checkout-barcode').trigger('focus'), 1 }); >- }); >- >- $('#pay-fine').click(function (event) { >- event.preventDefault(); >- recordFine($('#pay-fine-amount').val()); >- }); >- >- $('#mainform').submit(function (event) { >- event.preventDefault(); >- var barcode = $('#checkout-barcode').val(); >- $.indexedDB("koha").transaction(["items"]).then(function() { >- }, function(err, e){ >- }, function(transaction){ >- var items = transaction.objectStore("items"); >- items.get(barcode).done(function (item, error) { >- checkout(barcode, item, error); >- }); >- }); >- }); >- }); >- </script> >-[% END %] >- >-[% INCLUDE 'intranet-bottom.inc' %] >diff --git a/koha-tmpl/intranet-tmpl/prog/js/offlinecirc.js b/koha-tmpl/intranet-tmpl/prog/js/offlinecirc.js >deleted file mode 100644 >index 55c8af773c..0000000000 >--- a/koha-tmpl/intranet-tmpl/prog/js/offlinecirc.js >+++ /dev/null >@@ -1,113 +0,0 @@ >-/* Copyright 2013 C & P Bibliography Services >- * >- * This file is part of Koha. >- * >- * Koha is free software; you can redistribute it and/or modify it >- * under the terms of the GNU General Public License as published by >- * the Free Software Foundation; either version 3 of the License, or >- * (at your option) any later version. >- * >- * Koha 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 Koha; if not, see <http://www.gnu.org/licenses>. >- */ >- >-(function( kohadb, $, undefined ) { >- kohadb.settings = kohadb.settings || {}; >- kohadb.initialize = function (callback) { >- $.indexedDB("koha", { >- "version": 1, >- "schema": { >- "1": function(versionTransaction){ >- var patrons = versionTransaction.createObjectStore("patrons", { >- "keyPath": "cardnumber" >- }); >- var items = versionTransaction.createObjectStore("items", { >- "keyPath": "barcode" >- }); >- var issues = versionTransaction.createObjectStore("issues", { >- "keyPath": "barcode" >- }); >- issues.createIndex("cardnumber", { "multiEntry": true }); >- var transactions = versionTransaction.createObjectStore("transactions", { >- "keyPath": "timestamp" >- }); >- var settings = versionTransaction.createObjectStore("offline_settings", { >- "keyPath": "key" >- }); >- }, >- } >- }).done(function(){ >- if (typeof callback === 'function') { >- callback(); >- kohadb.loadSetting('userid'); >- kohadb.loadSetting('branchcode'); >- } >- }); >- }; >- kohadb.loadSetting = function (key, callback) { >- $.indexedDB("koha").transaction(["offline_settings"]).then(function(){ >- }, function(err, e){ >- if (typeof callback === 'function') { >- callback(key, undefined); >- } >- }, function(transaction){ >- var settings = transaction.objectStore("offline_settings"); >- settings.get(key).done(function (item, error) { >- if (typeof item !== 'undefined') { >- kohadb.settings[key] = item.value; >- } >- if (typeof callback === 'function') { >- callback(key, kohadb.settings[key]); >- } >- }); >- }); >- }; >- kohadb.saveSetting = function (key, value) { >- $.indexedDB("koha").transaction(["offline_settings"]).then(function(){ >- }, function(err, e){ >- }, function(transaction){ >- var settings = transaction.objectStore("offline_settings"); >- settings.put({ "key" : key, "value" : value }); >- kohadb.settings[key] = value; >- }); >- }; >- kohadb.recordTransaction = function (newtrans, callback) { >- $.indexedDB("koha").transaction(["transactions"]).then(function(){ >- callback(newtrans); >- }, function(err, e){ >- }, function(dbtransaction) { >- var transactions = dbtransaction.objectStore("transactions"); >- transactions.put(newtrans); >- kohadb.saveSetting('dirty', true); >- }); >- }; >-}( window.kohadb = window.kohadb || {}, jQuery )); >- >-if ( !Date.prototype.toMySQLString ) { >- ( function() { >- >- function pad(number) { >- var r = String(number); >- if ( r.length === 1 ) { >- r = '0' + r; >- } >- return r; >- } >- >- Date.prototype.toMySQLString = function() { >- return this.getFullYear() >- + '-' + pad( this.getMonth() + 1 ) >- + '-' + pad( this.getDate() ) >- + ' ' + pad( this.getHours() ) >- + ':' + pad( this.getMinutes() ) >- + ':' + pad( this.getSeconds() ) >- + '.' + String( (this.getMilliseconds()/1000).toFixed(3) ).slice( 2, 5 ); >- }; >- >- }() ); >-} >diff --git a/offline_circ/download.pl b/offline_circ/download.pl >deleted file mode 100755 >index ad120fd766..0000000000 >--- a/offline_circ/download.pl >+++ /dev/null >@@ -1,108 +0,0 @@ >-#!/usr/bin/perl >- >-# Copyright 2013 C & P Bibliography Services >-# >-# This file is part of Koha. >-# >-# Koha is free software; you can redistribute it and/or modify it >-# under the terms of the GNU General Public License as published by >-# the Free Software Foundation; either version 3 of the License, or >-# (at your option) any later version. >-# >-# Koha 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 Koha; if not, see <http://www.gnu.org/licenses>. >- >-use Modern::Perl; >-use CGI qw ( -utf8 ); >-use JSON qw( to_json ); >-use C4::Auth qw( checkauth ); >-use C4::Output; >-use C4::Context; >-use C4::Koha; >- >-my $query = CGI->new; >-checkauth( $query, undef, { circulate => "circulate_remaining_permissions" }, >- "intranet" ); >- >-my $page = $query->param('page') || 0; >-my $startrec = int($page) * 5000; >-my $req_data = $query->param('data') || ''; >- >-my $patrons_query = q{SELECT >- borrowers.borrowernumber, cardnumber, surname, firstname, title, >- othernames, initials, streetnumber, streettype, address, address2, city, >- state, zipcode, country, email, phone, mobile, fax, dateofbirth, borrowers.branchcode, >- categorycode, dateenrolled, dateexpiry, COALESCE(gonenoaddress, 0) AS gonenoaddress, >- COALESCE(lost, 0) AS lost, debarred, >- debarredcomment, SUM(accountlines.amountoutstanding) AS fine >- FROM borrowers >- LEFT JOIN accountlines ON borrowers.borrowernumber=accountlines.borrowernumber >- WHERE cardnumber IS NOT NULL >- GROUP BY borrowers.borrowernumber >- LIMIT ?, 5000; >- }; >- >-# NOTE: we can't fit very long titles on the interface so there isn't really any point in transferring them >-my $items_query = q{SELECT >- items.barcode AS barcode, items.itemnumber AS itemnumber, >- items.itemcallnumber AS callnumber, items.homebranch AS homebranch, >- items.holdingbranch AS holdingbranch, items.itype AS itemtype, >- items.materials AS materials, LEFT(biblio.title, 60) AS title, >- biblio.author AS author, biblio.biblionumber AS biblionumber >- FROM items >- JOIN biblio ON biblio.biblionumber = items.biblionumber >- WHERE barcode IS NOT NULL >- LIMIT ?, 5000; >- }; >- >-my $issues_query = q{SELECT >- biblio.title AS title, >- items.barcode AS barcode, >- items.itemcallnumber AS callnumber, >- issues.date_due AS date_due, >- issues.issuedate AS issuedate, >- issues.renewals_count AS renewals, >- issues.unseen_renewals AS unseen_renewals, >- borrowers.cardnumber AS cardnumber, >- CONCAT(borrowers.surname, ', ', borrowers.firstname) AS borrower_name >- FROM issues >- JOIN items ON items.itemnumber = issues.itemnumber >- JOIN biblio ON biblio.biblionumber = items.biblionumber >- JOIN borrowers ON borrowers.borrowernumber = issues.borrowernumber >- WHERE barcode IS NOT NULL >- LIMIT ?, 5000; >- }; >- >-my %results; >-my $finished = 1; >-if ( $req_data eq 'patrons' || $req_data eq 'all' ) { >- $results{'patrons'} = get_data( $patrons_query, 'cardnumber', $startrec ); >-} >-if ( $req_data eq 'items' || $req_data eq 'all' ) { >- $results{'items'} = get_data( $items_query, 'barcode', $startrec ); >-} >-if ( $req_data eq 'issues' || $req_data eq 'all' ) { >- $results{'issues'} = get_data( $issues_query, 'barcode', $startrec ); >-} >- >-foreach my $key ( keys %results ) { >- $finished = 0 if keys %{ $results{$key} } == 5000; >-} >-$results{'finished'} = $finished; >- >-print $query->header( -type => 'application/json', -charset => 'utf-8' ); >-print to_json( \%results ); >- >-sub get_data { >- my ( $sql, $key, $start ) = @_; >- $start ||= 0; >- my $dbh = C4::Context->dbh; >- my $sth = $dbh->prepare($sql); >- $sth->execute($start); >- return $sth->fetchall_hashref($key); >-} >-- >2.30.2
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 33961
:
152209
|
152210
|
152237
| 152243