diff --git a/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_appcache.xml b/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_appcache.xml
deleted file mode 100644
index 0ca6f86db83f00ac839602191d0e62812976d6f0..0000000000000000000000000000000000000000
--- a/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_appcache.xml
+++ /dev/null
@@ -1,414 +0,0 @@
-
-
-
-
-
-
-
-
- -
- _Access_contents_information_Permission
-
-
- Anonymous
- Assignee
- Assignor
- Associate
- Auditor
- Manager
-
-
-
- -
- _Add_portal_content_Permission
-
-
- Assignee
- Assignor
- Manager
-
-
-
- -
- _Change_local_roles_Permission
-
-
- Assignor
- Manager
-
-
-
- -
- _Modify_portal_content_Permission
-
-
- Assignee
- Assignor
- Manager
-
-
-
- -
- _View_Permission
-
-
- Anonymous
- Assignee
- Assignor
- Associate
- Auditor
- Manager
-
-
-
- -
- categories
-
-
-
-
- -
- content_md5
-
-
-
-
- -
- default_reference
- gadget_erp5.appcache
-
- -
- description
-
-
-
-
- -
- id
- rjs_gadget_erp5_appcache
-
- -
- language
- en
-
- -
- portal_type
- Web Manifest
-
- -
- short_title
-
-
-
-
- -
- text_content
- CACHE MANIFEST\n
-# generated on Wed, 21 Nov 2018 10:00:00 GMT+0100\n
-# XXX + fonts\n
-# images/ajax-loader.gif\n
-CACHE:\n
-favicon.ico\n
-font-awesome/font-awesome-webfont.eot\n
-font-awesome/font-awesome-webfont.woff\n
-font-awesome/font-awesome-webfont.woff2\n
-font-awesome/font-awesome-webfont.ttf\n
-font-awesome/font-awesome-webfont.svg\n
-gadget_erp5_worklist_empty.svg?format=svg\n
-erp5_launcher_nojqm.js\n
-gadget_erp5_nojqm.css\n
-gadget_erp5_configure_editor.html\n
-gadget_erp5_configure_editor.js\n
-gadget_erp5_editor_panel.html\n
-gadget_erp5_editor_panel.js\n
-gadget_erp5_field_checkbox.html\n
-gadget_erp5_field_checkbox.js\n
-gadget_erp5_field_datetime.html\n
-gadget_erp5_field_datetime.js\n
-gadget_erp5_field_editor.html\n
-gadget_erp5_field_editor.js\n
-gadget_erp5_field_email.html\n
-gadget_erp5_field_email.js\n
-gadget_erp5_field_file.html\n
-gadget_erp5_field_file.js\n
-gadget_erp5_field_float.html\n
-gadget_erp5_field_float.js\n
-gadget_erp5_field_formbox.html\n
-gadget_erp5_field_formbox.js\n
-gadget_erp5_field_gadget.html\n
-gadget_erp5_field_gadget.js\n
-gadget_erp5_field_image.html\n
-gadget_erp5_field_image.js\n
-gadget_erp5_field_integer.html\n
-gadget_erp5_field_integer.js\n
-gadget_erp5_field_list.html\n
-gadget_erp5_field_list.js\n
-gadget_erp5_field_lines.html\n
-gadget_erp5_field_lines.js\n
-gadget_erp5_field_listbox.html\n
-gadget_erp5_field_listbox.js\n
-gadget_erp5_field_matrixbox.html\n
-gadget_erp5_field_matrixbox.js\n
-gadget_erp5_field_multicheckbox.html\n
-gadget_erp5_field_multicheckbox.js\n
-gadget_erp5_field_multilist.html\n
-gadget_erp5_field_multilist.js\n
-gadget_erp5_field_multirelationstring.html\n
-gadget_erp5_field_multirelationstring.js\n
-gadget_erp5_field_radio.html\n
-gadget_erp5_field_radio.js\n
-gadget_erp5_field_readonly.html\n
-gadget_erp5_field_readonly.js\n
-gadget_erp5_field_relationstring.html\n
-gadget_erp5_field_relationstring.js\n
-gadget_erp5_field_string.html\n
-gadget_erp5_field_string.js\n
-gadget_erp5_field_password.html\n
-gadget_erp5_field_password.js\n
-gadget_erp5_field_textarea.html\n
-gadget_erp5_field_textarea.js\n
-gadget_erp5_form.html\n
-gadget_erp5_form.js\n
-gadget_erp5_header.html\n
-gadget_erp5_header.js\n
-gadget_erp5_jio.html\n
-gadget_erp5_jio.js\n
-gadget_erp5_label_field.html\n
-gadget_erp5_label_field.js\n
-gadget_erp5_notification.html\n
-gadget_erp5_notification.js\n
-gadget_erp5_page_action.html\n
-gadget_erp5_page_action.js\n
-gadget_erp5_page_export.html\n
-gadget_erp5_page_export.js\n
-gadget_erp5_page_form.html\n
-gadget_erp5_page_form.js\n
-gadget_erp5_page_front.html\n
-gadget_erp5_page_front.js\n
-gadget_erp5_page_history.html\n
-gadget_erp5_page_history.js\n
-gadget_erp5_page_jump.html\n
-gadget_erp5_page_jump.js\n
-gadget_erp5_page_language.html\n
-gadget_erp5_page_language.js\n
-gadget_erp5_page_logout.html\n
-gadget_erp5_page_logout.js\n
-gadget_erp5_page_preference.html\n
-gadget_erp5_page_preference.js\n
-gadget_erp5_page_relation_search.html\n
-gadget_erp5_page_relation_search.js\n
-gadget_erp5_page_search.html\n
-gadget_erp5_page_search.js\n
-gadget_erp5_page_tab.html\n
-gadget_erp5_page_tab.js\n
-gadget_erp5_page_worklist.html\n
-gadget_erp5_page_worklist.js\n
-gadget_erp5_panel.html\n
-gadget_erp5_panel.js\n
-gadget_erp5_panel.png?format=png\n
-gadget_erp5_pt_embedded_form_render.html\n
-gadget_erp5_pt_embedded_form_render.js\n
-gadget_erp5_pt_form_dialog.html\n
-gadget_erp5_pt_form_dialog.js\n
-gadget_erp5_pt_form_list.html\n
-gadget_erp5_pt_form_list.js\n
-gadget_erp5_pt_form_view.html\n
-gadget_erp5_pt_form_view.js\n
-gadget_erp5_pt_form_view_editable.html\n
-gadget_erp5_pt_form_view_editable.js\n
-gadget_erp5_pt_report_view.html\n
-gadget_erp5_pt_report_view.js\n
-gadget_erp5_router.html\n
-gadget_erp5_router.js\n
-gadget_erp5_relation_input.html\n
-gadget_erp5_relation_input.js\n
-gadget_erp5_search_editor.html\n
-gadget_erp5_search_editor.js\n
-gadget_erp5_searchfield.html\n
-gadget_erp5_searchfield.js\n
-gadget_erp5_sort_editor.html\n
-gadget_erp5_sort_editor.js\n
-gadget_global.js\n
-gadget_html5_element.html\n
-gadget_html5_element.js\n
-gadget_html5_input.html\n
-gadget_html5_input.js\n
-gadget_html5_textarea.html\n
-gadget_html5_textarea.js\n
-gadget_html5_select.html\n
-gadget_html5_select.js\n
-gadget_erp5_global.js\n
-gadget_jio.html\n
-gadget_jio.js\n
-gadget_translation.html\n
-gadget_translation.js\n
-gadget_translation_data.js\n
-gadget_editor.html\n
-gadget_editor.js\n
-gadget_button_maximize.html\n
-gadget_button_maximize.js\n
-handlebars.js\n
-jiodev.js\n
-renderjs.js\n
-rsvp.js\n
-NETWORK:\n
-*
-
- -
- title
- RenderJS Gadget ERP5 AppCache
-
- -
- version
- 001
-
- -
- workflow_history
-
- AAAAAAAAAAI=
-
-
-
-
-
-
-
-
-
-
-
- -
- data
-
-
-
-
- document_publication_workflow
-
- AAAAAAAAAAM=
-
-
- -
- edit_workflow
-
- AAAAAAAAAAQ=
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
- action
- publish_alive
-
- -
- actor
- zope
-
- -
- comment
-
-
- -
- error_message
-
-
- -
- time
-
-
-
-
- -
- validation_state
- published_alive
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
- action
- edit
-
- -
- actor
- zope
-
- -
- comment
-
-
-
-
- -
- error_message
-
-
- -
- serial
- 971.39427.41235.63641
-
- -
- state
- current
-
- -
- time
-
-
-
-
-
-
-
-
-
-
diff --git a/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_launcher_js.js b/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_launcher_js.js
index 88a42dbdcccc738ec30bd8600dc329a9be5f0633..55293e15f525218b1ed47384d826ebc79c2ce992 100644
--- a/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_launcher_js.js
+++ b/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_launcher_js.js
@@ -1,8 +1,10 @@
/*globals window, document, RSVP, rJS,
- URI, location, XMLHttpRequest, console, navigator, Event*/
+ URI, location, XMLHttpRequest, console, navigator, Event,
+ URL*/
/*jslint indent: 2, maxlen: 80*/
(function (window, document, RSVP, rJS,
- XMLHttpRequest, location, console, navigator, Event) {
+ XMLHttpRequest, location, console, navigator, Event,
+ URL) {
"use strict";
var MAIN_SCOPE = "m",
@@ -823,7 +825,34 @@
.onEvent('submit', function submit() {
return displayError(this, new Error("Unexpected form submit"));
+ })
+
+ /////////////////////////////////////////////////////////////////
+ // For Firefox, Wallpaper URL must be absolute one.
+ /////////////////////////////////////////////////////////////////
+ .declareService(function () {
+ var index, styleSheet, wallpaper_url, wallpaper_absolute_url;
+ if (navigator.userAgent.toLowerCase().indexOf('firefox') > -1) {
+ for (index = 0; index < document.styleSheets.length; index += 1) {
+ styleSheet = document.styleSheets[index];
+ if (styleSheet.href.startsWith('data:text/css;')) {
+ wallpaper_url = styleSheet.cssRules[0].style
+ .backgroundImage.slice(4, -1).replace(/["']/g, '');
+ wallpaper_absolute_url = new URL(
+ wallpaper_url,
+ window.location.toString()
+ );
+ styleSheet.cssRules[0].style.backgroundImage =
+ 'url("' + wallpaper_absolute_url.href + '")';
+ break;
+ }
+ }
+ index = null;
+ styleSheet = null;
+ wallpaper_url = null;
+ wallpaper_absolute_url = null;
+ }
});
}(window, document, RSVP, rJS,
- XMLHttpRequest, location, console, navigator, Event));
\ No newline at end of file
+ XMLHttpRequest, location, console, navigator, Event, URL));
\ No newline at end of file
diff --git a/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_launcher_js.xml b/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_launcher_js.xml
index 5159212f3cf5e0914e66dafa75f9ddf71904e342..6196777ed1ed5d88ff8a1cb53829b5fa20531432 100644
--- a/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_launcher_js.xml
+++ b/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_launcher_js.xml
@@ -228,7 +228,7 @@
-
serial
- 975.29292.10042.3754
+ 978.15454.53878.14950
-
state
@@ -246,7 +246,7 @@
- 1556870187.8
+ 1567693410.93
UTC
diff --git a/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_serviceworker.js b/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_serviceworker.js
index 18cc8104de0d8dbc75d00f15ae733c9c7a5707c6..88e58e87c29adeaa6eecbfc98464ce92d95df193 100644
--- a/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_serviceworker.js
+++ b/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_serviceworker.js
@@ -1,33 +1,43 @@
/*jslint indent: 2*/
-/*global self, caches, fetch*/
-(function (self, caches, fetch) {
+/*global self, caches, fetch, Promise, URL, location, Response*/
+(function (self, caches, fetch, Promise, URL, location, Response) {
"use strict";
- var CACHE_NAME = 'Thu, 12 July 2016 12:00:00 GMT',
+ var prefix = location.toString() + '_',
+ // CLIENT_CACHE_MAPPING_NAME must not start with `prefix`
+ // else it may be used as a normal content cache.
+ CLIENT_CACHE_MAPPING_NAME = '__erp5js_' + location.toString(),
+ CACHE_NAME = prefix + '_0001',
+ CACHE_MAP = {},
// Files required to make this app work offline
REQUIRED_FILES = [
- './',
- 'https://netdna.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css',
- 'https://netdna.bootstrapcdn.com/font-awesome/4.2.0/fonts/fontawesome-webfont.eot?v=4.2.0',
- 'https://netdna.bootstrapcdn.com/font-awesome/4.2.0/fonts/fontawesome-webfont.eot?#iefix&v=4.2.0',
- 'https://netdna.bootstrapcdn.com/font-awesome/4.2.0/fonts/fontawesome-webfont.woff?v=4.2.0',
- 'https://netdna.bootstrapcdn.com/font-awesome/4.2.0/fonts/fontawesome-webfont.ttf?v=4.2.0',
- 'https://netdna.bootstrapcdn.com/font-awesome/4.2.0/fonts/fontawesome-webfont.svg?v=4.2.0#fontawesomeregular',
- 'URI.js',
- 'erp5_launcher.js',
- 'gadget_erp5.css',
+ 'favicon.ico',
+ 'font-awesome/font-awesome-webfont.eot',
+ 'font-awesome/font-awesome-webfont.woff',
+ 'font-awesome/font-awesome-webfont.woff2',
+ 'font-awesome/font-awesome-webfont.ttf',
+ 'font-awesome/font-awesome-webfont.svg',
+ 'gadget_erp5_worklist_empty.svg?format=svg',
+ 'erp5_launcher_nojqm.js',
+ 'gadget_erp5_nojqm.css',
+ 'gadget_erp5_configure_editor.html',
+ 'gadget_erp5_configure_editor.js',
'gadget_erp5_editor_panel.html',
'gadget_erp5_editor_panel.js',
'gadget_erp5_field_checkbox.html',
'gadget_erp5_field_checkbox.js',
'gadget_erp5_field_datetime.html',
'gadget_erp5_field_datetime.js',
+ 'gadget_erp5_field_editor.html',
+ 'gadget_erp5_field_editor.js',
'gadget_erp5_field_email.html',
'gadget_erp5_field_email.js',
'gadget_erp5_field_file.html',
'gadget_erp5_field_file.js',
'gadget_erp5_field_float.html',
'gadget_erp5_field_float.js',
+ 'gadget_erp5_field_formbox.html',
+ 'gadget_erp5_field_formbox.js',
'gadget_erp5_field_gadget.html',
'gadget_erp5_field_gadget.js',
'gadget_erp5_field_image.html',
@@ -36,8 +46,12 @@
'gadget_erp5_field_integer.js',
'gadget_erp5_field_list.html',
'gadget_erp5_field_list.js',
+ 'gadget_erp5_field_lines.html',
+ 'gadget_erp5_field_lines.js',
'gadget_erp5_field_listbox.html',
'gadget_erp5_field_listbox.js',
+ 'gadget_erp5_field_matrixbox.html',
+ 'gadget_erp5_field_matrixbox.js',
'gadget_erp5_field_multicheckbox.html',
'gadget_erp5_field_multicheckbox.js',
'gadget_erp5_field_multilist.html',
@@ -62,8 +76,14 @@
'gadget_erp5_header.js',
'gadget_erp5_jio.html',
'gadget_erp5_jio.js',
+ 'gadget_erp5_label_field.html',
+ 'gadget_erp5_label_field.js',
+ 'gadget_erp5_notification.html',
+ 'gadget_erp5_notification.js',
'gadget_erp5_page_action.html',
'gadget_erp5_page_action.js',
+ 'gadget_erp5_page_export.html',
+ 'gadget_erp5_page_export.js',
'gadget_erp5_page_form.html',
'gadget_erp5_page_form.js',
'gadget_erp5_page_front.html',
@@ -72,6 +92,8 @@
'gadget_erp5_page_history.js',
'gadget_erp5_page_jump.html',
'gadget_erp5_page_jump.js',
+ 'gadget_erp5_page_language.html',
+ 'gadget_erp5_page_language.js',
'gadget_erp5_page_logout.html',
'gadget_erp5_page_logout.js',
'gadget_erp5_page_preference.html',
@@ -86,6 +108,9 @@
'gadget_erp5_page_worklist.js',
'gadget_erp5_panel.html',
'gadget_erp5_panel.js',
+ 'gadget_erp5_panel.png?format=png',
+ 'gadget_erp5_pt_embedded_form_render.html',
+ 'gadget_erp5_pt_embedded_form_render.js',
'gadget_erp5_pt_form_dialog.html',
'gadget_erp5_pt_form_dialog.js',
'gadget_erp5_pt_form_list.html',
@@ -107,45 +132,208 @@
'gadget_erp5_sort_editor.html',
'gadget_erp5_sort_editor.js',
'gadget_global.js',
+ 'gadget_html5_element.html',
+ 'gadget_html5_element.js',
+ 'gadget_html5_input.html',
+ 'gadget_html5_input.js',
+ 'gadget_html5_textarea.html',
+ 'gadget_html5_textarea.js',
+ 'gadget_html5_select.html',
+ 'gadget_html5_select.js',
'gadget_erp5_global.js',
'gadget_jio.html',
'gadget_jio.js',
'gadget_translation.html',
'gadget_translation.js',
'gadget_translation_data.js',
+ 'gadget_editor.html',
+ 'gadget_editor.js',
+ 'gadget_button_maximize.html',
+ 'gadget_button_maximize.js',
'handlebars.js',
- 'i18next.js',
'jiodev.js',
'renderjs.js',
- 'rsvp.js'
- ];
+ 'rsvp.js',
+ './'
+ ],
+ required_url_list = [],
+ i,
+ len = REQUIRED_FILES.length;
+ for (i = 0; i < len; i += 1) {
+ required_url_list.push(
+ new URL(REQUIRED_FILES[i], location.toString()).toString()
+ );
+ }
self.addEventListener('install', function (event) {
// Perform install step: loading each required file into cache
event.waitUntil(
- caches.open(CACHE_NAME)
- .then(function (cache) {
- // Add all offline dependencies to the cache
- return cache.addAll(REQUIRED_FILES);
- })
- .then(function () {
- // At this point everything has been cached
- return self.skipWaiting();
+ // We create cache only if it does not exist. That is because
+ // we do not want to override an existing cache by mistake.
+ // Code consistency is very important. We must not mix different
+ // versions of code.
+ // (For example, developer change service worker code and forget
+ // to increase the cache version.)
+ caches.has(CACHE_NAME)
+ .then(function (result) {
+ if (!result) {
+ caches.open(CACHE_NAME)
+ .then(function (cache) {
+ // Add all offline dependencies to the cache
+ return Promise.all(
+ REQUIRED_FILES
+ .map(function (url) {
+ /* Return a promise that's fulfilled
+ when each url is cached.
+ */
+ // Use cache.add because safari does not support cache.addAll.
+ console.log("Install " + CACHE_NAME + " = " + url);
+ return cache.add(url);
+ })
+ );
+ })
+ .then(function () {
+ return caches.keys();
+ })
+ .then(function (keys) {
+ keys = keys.filter(function (key) {return key.startsWith(prefix); });
+ if (keys.length === 1) {
+ // When user accesses ERP5JS web site first time, service worker is
+ // installed but it is not activated yet, service worker is activated
+ // when the page is refreshed or when a new tab opens the site again.
+ // If user does not refresh the page and continue to use the site,
+ // user can't use cache, so everything becomes slow. We must avoid this
+ // situation.
+ // So, we want to activate the new service worker immediately if it was
+ // the first one. (We must not activate the new service worker by
+ // skipWaiting if there is already an active service worker because it
+ // causes code inconsistency by loading code from a different version of
+ // cache.
+ // If there is only one cache, it means that this is the first service worker,
+ // thus we can do skipWaiting. And self.registration is unreliable on
+ // Firefox, we can't use self.registration.active
+ return self.skipWaiting();
+ }
+ })
+ .catch(function (error) {
+ // Since we do not allow to override existing cache, if cache installation
+ // failed, we need to delete the cache completely.
+ caches.delete(CACHE_NAME);
+ // Explicitly unregister service worker else it may not be done.
+ self.registration.unregister();
+ throw error;
+ });
+ }
})
);
});
self.addEventListener('fetch', function (event) {
- event.respondWith(
- caches.match(event.request)
+ /* When a new service worker is installed, it adds a new Cache
+ to Cache Storage. When a new client started using this
+ service worker, the new client uses the latest Cache at
+ that time by comparing with Cache keys. And once the client
+ is associated with a Cache key, it keeps using the same Cache
+ key, it must not use different Caches. Since service worker
+ is stateless, to maintain the mapping of client and Cache key,
+ we use Cache Storage as a persistent data store. The key of
+ this special Cache is CLIENT_CACHE_MAPPING_NAME.
+ */
+ var url = new URL(event.request.url),
+ client_id = event.clientId.toString(),
+ // CACHE_MAP is a temprary data store.
+ // This should be kept until service worker stops.
+ cache_key,
+ erp5js_cache;
+ url.hash = '';
+ if (client_id) {
+ // client_id is null when it is the first request, in other words
+ // if request is navigate mode. Since major web browsers already
+ // implement client_id, if client_is is null, let's use the latest cache
+ // and don't get cache_key from CACHE_MAP and erp5js_cache.
+ cache_key = CACHE_MAP[client_id];
+ }
+ console.log("Client Id = " + client_id);
+
+ if (cache_key) {
+ console.log("cache_key from CACHE_MAP " + cache_key);
+ }
+
+ if ((event.request.method !== 'GET') ||
+ (required_url_list.indexOf(url.toString()) === -1)) {
+ // Try not to use the untrustable fetch function
+ // It can only be skip synchronously
+ return;
+ }
+ return event.respondWith(
+ Promise.resolve()
+ .then(function () {
+ if (!cache_key) {
+ // CLIENT_CACHE_MAPPING_NAME stores cache_key of each client.
+ return caches.open(CLIENT_CACHE_MAPPING_NAME)
+ .then(function (cache) {
+ // Service worker forget everything when it stops. So, when it started
+ // again, CACHE_MAP is empty, get the associated cache_key from the
+ // special Cache named CLIENT_CACHE_MAPPING_NAME.
+ erp5js_cache = cache;
+ return erp5js_cache.match(client_id)
+ .then(function (response) {
+ if (response) {
+ // We use Cache Storage as a persistent database.
+ cache_key = response.statusText;
+ CACHE_MAP[client_id] = cache_key;
+ console.log("cache_key from Cache Storage " + cache_key);
+ }
+ });
+ });
+ }
+ })
+ .then(function () {
+ if (!cache_key) {
+ // If associated cache_key is not found, it means this client is a new one.
+ // Let's find the latest Cache.
+ return caches.keys()
+ .then(function (keys) {
+ keys = keys.filter(function (key) {return key.startsWith(prefix); });
+ console.log("KEYS = " + keys);
+ if (keys.length) {
+ cache_key = keys.sort().reverse()[0];
+ if (client_id) {
+ CACHE_MAP[client_id] = cache_key;
+ }
+ } else {
+ cache_key = CACHE_NAME;
+ if (client_id) {
+ CACHE_MAP[client_id] = CACHE_NAME;
+ }
+ }
+ // Save the associated cache_key in a persistent database because service
+ // worker forget everything when it stops.
+ if (client_id) {
+ erp5js_cache.put(client_id, new Response(null, {"statusText": cache_key}));
+ }
+ });
+ }
+ })
+ .then(function () {
+ // Finally we have the associated cache_key. Let's find a cached response.
+ return caches.open(cache_key);
+ })
+ .then(function (cache) {
+ // Don't give request object itself. Firefox's Cache Storage
+ // does not work properly when VARY contains Accept-Language.
+ // Give URL string instead, then cache.match works on both Firefox and Chrome.
+ console.log("MATCH " + cache_key + " " + url);
+ return cache.match(event.request.url);
+ })
.then(function (response) {
// Cache hit - return the response from the cached version
if (response) {
return response;
}
-
// Not in cache - return the result from the live server
// `fetch` is essentially a "fallback"
+ console.log("MISS " + cache_key + " " + url);
return fetch(event.request);
})
);
@@ -162,14 +350,16 @@
*/
.keys()
.then(function (keys) {
+ keys = keys
+ .filter(function (key) {
+ // Filter by keys that don't start with the latest version prefix.
+ return key.startsWith(prefix);
+ })
+ .sort();
+ keys = keys.slice(0, keys.findIndex(function (element) {return element === CACHE_NAME; }));
// We return a promise that settles when all outdated caches are deleted.
return Promise.all(
keys
- .filter(function (key) {
- // Filter by keys that don't start with the latest version prefix.
- // return !key.startsWith(version);
- return key !== CACHE_NAME;
- })
.map(function (key) {
/* Return a promise that's fulfilled
when each outdated cache is deleted.
@@ -179,11 +369,12 @@
);
})
.then(function () {
- self.clients.claim();
+ // If new service worker becomes active, it means that all clients
+ // (tabs, windows, etc) were already closed. Thus we can remove the
+ // client cache mapping.
+ caches.delete(CLIENT_CACHE_MAPPING_NAME);
})
);
});
-
-
-}(self, caches, fetch));
+}(self, caches, fetch, Promise, URL, location, Response));
\ No newline at end of file
diff --git a/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_serviceworker.xml b/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_serviceworker.xml
index 1bf7499acccb10b8c48c8672b04b4b51f0d9795b..3f7b07d28fb827dc4e386582f1374971ae6aa627 100644
--- a/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_serviceworker.xml
+++ b/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_page_module/rjs_gadget_erp5_serviceworker.xml
@@ -228,7 +228,7 @@
-
serial
- 952.5891.40125.8465
+ 976.56996.62202.65433
-
state
@@ -246,7 +246,7 @@
- 1467035757.8
+ 1562322109.66
UTC
diff --git a/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_site_module/renderjs_runner.xml b/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_site_module/renderjs_runner.xml
index a611df1bbd44e27a8a9694979123e196bf3bc0f1..8baccec07c75c3da1a6a196c578f819e98b427fa 100644
--- a/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_site_module/renderjs_runner.xml
+++ b/bt5/erp5_web_renderjs_ui/PathTemplateItem/web_site_module/renderjs_runner.xml
@@ -279,6 +279,16 @@
string
+
+ -
+ id
+ configuration_service_worker_url
+
+ -
+ type
+ string
+
+
@@ -353,12 +363,18 @@
-
configuration_manifest_url
- gadget_erp5.appcache
+
+
+
-
configuration_panel_gadget_url
gadget_erp5_panel.html
+ -
+ configuration_service_worker_url
+ gadget_erp5_serviceworker.js
+
-
configuration_translation_gadget_url
gadget_translation.html
@@ -600,7 +616,7 @@
-
serial
- 965.19244.13768.6758
+ 973.33482.4166.8669
-
state
@@ -618,7 +634,7 @@
- 1517843997.55
+ 1553593373.77
UTC
diff --git a/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs/Base_createTranslateData.py b/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs/Base_createTranslateData.py
index 403f2553f93d2d7544cc9d417a9ca35b36901757..f96655a06a9d9ef43a5c1ae744d68e97239be739 100644
--- a/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs/Base_createTranslateData.py
+++ b/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs/Base_createTranslateData.py
@@ -15,7 +15,7 @@ tmp_re = re.compile(r"""/[{}]/g, """"")
translate_word = []
for web_page in portal.web_page_module.searchFolder(portal_type='Web Page',
- reference=context.Base_getListFileFromAppcache(only_html=1)):
+ reference=context.Base_getTranslationSourceFileList(only_html=1)):
data = attribute_filter_re.findall(web_page.getTextContent())
for attribute in data:
a = re.sub(r'[{|}]', "", attribute[1])
diff --git a/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs/Base_getListFileFromAppcache.py b/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs/Base_getListFileFromAppcache.py
deleted file mode 100644
index abfbeb8f01508bf29ae14c15e7563e8a597fd12a..0000000000000000000000000000000000000000
--- a/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs/Base_getListFileFromAppcache.py
+++ /dev/null
@@ -1,21 +0,0 @@
-appcache_file = context.getLayoutProperty("configuration_manifest_url", default="gadget_erp5.appcache")
-
-
-text_content = context.web_page_module.searchFolder(
- portal_type= 'Web Manifest',
- reference = appcache_file)[0].getTextContent()
-
-translation_data_file = []
-file_list = []
-for file in text_content.split('\n'):
- file = file.split('/')[-1]
- if file.endswith('.html'):
- file_list.append(file)
- continue
-
- if file.endswith('.js') and not only_html:
- if file.endswith('translation_data.js'):
- translation_data_file = [file]
- continue
- file_list.append(file)
-return translation_data_file + file_list
diff --git a/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs/Base_getTranslationSourceFileList.py b/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs/Base_getTranslationSourceFileList.py
new file mode 100644
index 0000000000000000000000000000000000000000..280375918d95b40afcb1834bbcfd4b008741cd80
--- /dev/null
+++ b/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs/Base_getTranslationSourceFileList.py
@@ -0,0 +1,40 @@
+import re
+
+service_worker_reference = context.getLayoutProperty("configuration_service_worker_url", default="gadget_erp5_serviceworker.js")
+
+text_content = context.web_page_module.searchFolder(
+ portal_type='Web Script',
+ reference=service_worker_reference)[0].getTextContent()
+
+filename_pattern = re.compile("'(?P[a-zA-Z0-9-_\.\?=]*)'")
+filename_list = []
+
+start = False
+for line in text_content.split('\n'):
+ if start is False and 'REQUIRED_FILES' in line:
+ start = True
+ continue
+ if not line:
+ continue
+ if start:
+ if ']' in line:
+ break
+ matched = filename_pattern.search(line)
+ if matched is not None:
+ filename = matched.groupdict().get('filename')
+ if filename:
+ filename_list.append(filename)
+
+file_list = []
+translation_data_file = []
+for filename in filename_list:
+ if filename.endswith('.html'):
+ file_list.append(filename)
+ continue
+
+ if filename.endswith('.js') and not only_html:
+ if filename.endswith('translation_data.js'):
+ translation_data_file = [filename]
+ continue
+ file_list.append(filename)
+return translation_data_file + file_list
diff --git a/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs/Base_getListFileFromAppcache.xml b/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs/Base_getTranslationSourceFileList.xml
similarity index 93%
rename from bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs/Base_getListFileFromAppcache.xml
rename to bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs/Base_getTranslationSourceFileList.xml
index f7d497e57e17124e7ae5fced7c599eee7f3aaf0c..3240f07cc5fded60945af1770a9d612e060fcbcc 100644
--- a/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs/Base_getListFileFromAppcache.xml
+++ b/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs/Base_getTranslationSourceFileList.xml
@@ -50,11 +50,11 @@
-
_params
- only_html = 0
+ only_html=0
-
id
- Base_getListFileFromAppcache
+ Base_getTranslationSourceFileList
diff --git a/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs/WebSite_createTranslationData/your_translation_data_file.xml b/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs/WebSite_createTranslationData/your_translation_data_file.xml
index 1246765abd292e9e581cd0482e20a016e319d36d..73d7ae53e9f73103b39aba4e18c2dd940c7fdb6c 100644
--- a/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs/WebSite_createTranslationData/your_translation_data_file.xml
+++ b/bt5/erp5_web_renderjs_ui/SkinTemplateItem/portal_skins/erp5_web_renderjs/WebSite_createTranslationData/your_translation_data_file.xml
@@ -54,6 +54,10 @@
field_id
+ -
+ first_item
+
+
-
form_id
@@ -64,6 +68,10 @@
AAAAAAAAAAI=
+ -
+ title
+
+
@@ -107,7 +115,7 @@
-
_text
- python: [ (x,x) for x in here.Base_getListFileFromAppcache()]
+ python: [ (x,x) for x in here.Base_getTranslationSourceFileList()]
diff --git a/tests/__init__.py b/tests/__init__.py
index 580935d622e98b70ce2b2f976a2339adbca29f28..408e1366e5501c3770a6bb1a74b7bc39021b9450 100644
--- a/tests/__init__.py
+++ b/tests/__init__.py
@@ -1,12 +1,13 @@
from glob import glob
import os, subprocess, re
# test_suite is provided by 'run_test_suite'
-from test_suite import ERP5TypeTestSuite
+from test_suite import SavedTestSuite
import sys
HERE = os.path.dirname(__file__)
-class _ERP5(ERP5TypeTestSuite):
+class _ERP5(SavedTestSuite):
+ _saved_test_id = "erp5_web_renderjs_ui_test:testFunctionalRJSInterfaceValidator"
realtime_output = False
enabled_product_list = ('CMFActivity', 'CMFCategory', 'ERP5', 'ERP5Catalog',
'ERP5eGovSecurity', 'ERP5Form',
@@ -35,9 +36,27 @@ class _ERP5(ERP5TypeTestSuite):
component_re = re.compile(".*/([^/]+)/TestTemplateItem/portal_components"
"/test\.[^.]+\.([^.]+).py$")
for test_path in (
- glob('%s/product/*/tests/test*.py' % path) +
- glob('%s/bt5/*/TestTemplateItem/test*.py' % path) +
- glob('%s/bt5/*/TestTemplateItem/portal_components/test.*.test*.py' % path)):
+ # glob('%s/product/Formulator/tests/test*.py' % path) +
+ # glob('%s/product/ERP5Form/tests/test*.py' % path) +
+ # ['%s/product/ERP5/tests/testXHTML.py' % path] +
+ # ['%s/product/ERP5Type/tests/testFunctionalCore.py' % path] +
+ # ['%s/product/ERP5Type/tests/testFunctionalAnonymousSelection.py' % path] +
+ glob('%s/bt5/erp5_hal_json_style/TestTemplateItem/portal_components/test.*.test*.py' % path) +
+ glob('%s/bt5/erp5_web_renderjs_ui_test/TestTemplateItem/portal_components/test.*.test*.py' % path) +
+ # glob('%s/bt5/erp5_web_ui_test/TestTemplateItem/portal_components/test.*.test*.py' % path) +
+ # glob('%s/bt5/erp5_ui_test/TestTemplateItem/portal_components/test.*.test*.py' % path) +
+ # glob('%s/bt5/erp5_token_login/TestTemplateItem/portal_components/test.*.test*.py' % path) +
+ glob('%s/bt5/erp5_pdm_renderjs_ui_test/TestTemplateItem/portal_components/test.*.test*.py' % path) +
+ glob('%s/bt5/erp5_crm_renderjs_ui_test/TestTemplateItem/portal_components/test.*.test*.py' % path) +
+ glob('%s/bt5/erp5_accounting_renderjs_ui_test/TestTemplateItem/portal_components/test.*.test*.py' % path) +
+ glob('%s/bt5/erp5_gadget_interface_validator_ui_test/TestTemplateItem/portal_components/test.*.test*.py' % path)
+ # glob('%s/bt5/erp5_web_monitoring_ui_test/TestTemplateItem/portal_components/test.*.test*.py' % path) +
+ # glob('%s/bt5/erp5_travel_expense_ui_test/TestTemplateItem/portal_components/test.*.test*.py' % path) +
+ # glob('%s/bt5/erp5_officejs_support_request_ui_test/TestTemplateItem/portal_components/test.*.test*.py' % path) +
+ # glob('%s/bt5/erp5_officejs_afs_directory_ui_test/TestTemplateItem/portal_components/test.*.test*.py' % path) +
+ # glob('%s/bt5/erp5_officejs_ui_test/TestTemplateItem/portal_components/test.*.test*.py' % path)
+ ):
+ # glob('%s/bt5/erp5_web/TestTemplateItem/portal_components/test.*.test*.py' % path)):
component_re_match = component_re.match(test_path)
if component_re_match is not None:
test_case = "%s:%s" % (component_re_match.group(1),