diff --git a/controllers/FilesApiController.php b/controllers/FilesApiController.php
index c9aec10b..7577b58c 100644
--- a/controllers/FilesApiController.php
+++ b/controllers/FilesApiController.php
@@ -72,6 +72,7 @@ class FilesApiController extends BaseApiController
if (file_exists($filePath))
{
+ // TODO: ACCEPT JSON
$response->write(file_get_contents($filePath));
$response = $response->withHeader('Cache-Control', 'max-age=2592000');
$response = $response->withHeader('Content-Type', mime_content_type($filePath));
diff --git a/js/components/batterycard.js b/js/components/batterycard.js
index 1419b59c..7ca7cb31 100644
--- a/js/components/batterycard.js
+++ b/js/components/batterycard.js
@@ -11,6 +11,8 @@ class batterycard
this.scope = scopeSelector != null ? $(scopeSelector) : $(document);
var jScope = this.scope;
this.$ = scopeSelector != null ? (selector) => jScope.find(selector) : $;
+
+ this.Grocy.PreloadView("batteriesjournal");
}
Refresh(batteryId)
diff --git a/js/components/chorecard.js b/js/components/chorecard.js
index 441c5ff0..2c3be41a 100644
--- a/js/components/chorecard.js
+++ b/js/components/chorecard.js
@@ -11,6 +11,8 @@ class chorecard
this.scope = scopeSelector != null ? $(scopeSelector) : $(document);
var jScope = this.scope;
this.$ = scopeSelector != null ? (selector) => jScope.find(selector) : $;
+
+ this.Grocy.PreloadView("choresjournal");
}
Refresh(choreId)
diff --git a/js/components/productcard.js b/js/components/productcard.js
index e0b2532a..e9f6942a 100644
--- a/js/components/productcard.js
+++ b/js/components/productcard.js
@@ -28,6 +28,10 @@ class productcard
.find("a[data-toggle='collapse']")
.text(self.Grocy.translate("Show more"));
})
+
+ // preload some views.
+ this.Grocy.PreloadView("stockentries");
+ this.Grocy.PreloadView("stockjournal");
}
Refresh(productId)
diff --git a/js/configs/globalstate.js b/js/configs/globalstate.js
index e3f272a1..6b034827 100644
--- a/js/configs/globalstate.js
+++ b/js/configs/globalstate.js
@@ -190,22 +190,7 @@ function setInitialGlobalState(Grocy)
var link = $(e.currentTarget).attr("href");
- bootbox.dialog({
- message: '',
- size: 'large',
- backdrop: true,
- closeButton: false,
- buttons: {
- cancel: {
- label: __t('Close'),
- className: 'btn-secondary responsive-button',
- callback: function()
- {
- bootbox.hideAll();
- }
- }
- }
- });
+ Grocy.OpenSubView(link);
});
// serializeJSON defaults
diff --git a/js/grocy.js b/js/grocy.js
index 5970881f..6f272818 100644
--- a/js/grocy.js
+++ b/js/grocy.js
@@ -13,6 +13,8 @@ import { animateCSS, BoolVal, EmptyElementWhenMatches } from "./helpers/extensio
import Translator from "gettext-translator";
import { WindowMessageBag } from './helpers/messagebag';
import * as components from './components';
+import * as uuid from 'uuid';
+import { GrocyProxy } from "./lib/proxy";
import "./helpers/string";
@@ -54,6 +56,8 @@ class GrocyClass
this.initComponents = [];
this.RootGrocy = null;
+ this.documentReady = false;
+ this.preloadViews = [];
// Init some classes
this.Api = new GrocyApi(this);
@@ -114,6 +118,18 @@ class GrocyClass
}
});
}
+
+ $(document).on('ready', () =>
+ {
+ this.documentReady = true;
+ var element = self.preloadViews.pop();
+ while (element !== undefined)
+ {
+ self.preloadViews(element.viewName, element.loadCss, element.cb);
+
+ element = self.preloadViews.pop();
+ }
+ })
}
static createSingleton(config, view)
@@ -240,11 +256,19 @@ class GrocyClass
}
}
- LoadView(viewName, scope = null)
+ LoadView(viewName, scope = null, grocy = null)
{
if (Object.prototype.hasOwnProperty.call(window, viewName + "View"))
{
- window[viewName + "View"](this, scope);
+ if (scope != null && grocy == null)
+ {
+ console.warn("scoped view set but non-scoped grocy is used. Results are undefined!");
+ }
+ if (scope == null)
+ {
+ grocy = this;
+ }
+ window[viewName + "View"](grocy, scope);
}
else
{
@@ -254,6 +278,12 @@ class GrocyClass
PreloadView(viewName, loadCSS = false, cb = () => { })
{
+ if (!this.documentReady)
+ {
+ this.preloadViews.push({ viewName: viewName, loadCss: loadCss, cb: cb });
+ return;
+ }
+
if (!Object.prototype.hasOwnProperty.call(window, viewName + "View"))
{
$.ajax({
@@ -277,6 +307,46 @@ class GrocyClass
}
}
+ OpenSubView(link)
+ {
+ var self = this;
+ $.ajax({
+ dataType: "json",
+ link,
+ success: (data) =>
+ {
+ let scopeId = uuid.v4()
+ var proxy = new GrocyProxy(this, "#" + scopeId, data.config, link);
+
+ bootbox.dialog({
+ message: '
' + data.template + '
',
+ size: 'large',
+ backdrop: true,
+ closeButton: false,
+ buttons: {
+ cancel: {
+ label: self.translate('Close'),
+ className: 'btn-secondary responsive-button',
+ callback: function()
+ {
+ proxy.Unload();
+ bootbox.hideAll();
+ }
+ }
+ },
+ onShow: () =>
+ {
+ // dialog div is alive, init view.
+ // this occurs before the view is shown.
+ self.LoadView(data.viewJsName, "#" + scopeId, proxy);
+ }
+ });
+ }
+ })
+
+
+ }
+
UndoStockBooking(bookingId)
{
var self = this;
diff --git a/js/lib/proxy.js b/js/lib/proxy.js
index 511ae436..ddc5600b 100644
--- a/js/lib/proxy.js
+++ b/js/lib/proxy.js
@@ -31,12 +31,20 @@ class GrocyProxy
// scoping
this.scopeSelector = scopeSelector;
- this.scope = $(scope);
- this.$scope = this.scope.find;
+ this.scope = $(scopeSelector);
+ var jScope = this.scope;
+ this.$scope = (selector) => jScope.find(selector);
var queryString = url.split('?', 2);
this.virtualUrl = queryString.length == 2 ? queryString[1] : ""; // maximum two parts
this.config = config;
+ if (Object.prototype.hasOwnProperty.call(this.config, "UserSettings"))
+ {
+ // if we need to override UserSettings, we need to copy the object.
+ // not great, but eh.
+ Object.assign(this.config.UserSettings, RootGrocy.UserSettings);
+ this.UserSettings = config.UserSettings;
+ }
this.configProxy = Proxy.revocable(this.config, {
get: function(target, prop, receiver)
@@ -47,7 +55,7 @@ class GrocyProxy
}
else
{
- return Reflect.get(rootGrocy.config, prop, target);
+ return Reflect.get(RootGrocy.config, prop, target);
}
}
})
@@ -130,10 +138,10 @@ class GrocyProxy
UpdateUriParam(key, value)
{
- params = {}
+ var params = {}
var vars = this.virtualUrl.split("&");
- for (part of vars)
+ for (let part of vars)
{
var lkey, lvalue;
[lkey, lvalue = null] = part.split('=');
@@ -144,6 +152,7 @@ class GrocyProxy
params[key] = value;
var vurl = ""
+
for ([key, value] of params)
{
vurl += "&" + key
@@ -157,10 +166,10 @@ class GrocyProxy
RemoveUriParam(key)
{
- params = {}
+ var params = {}
var vars = this.virtualUrl.split("&");
- for (part of vars)
+ for (let part of vars)
{
var lkey, lvalue;
[lkey, lvalue = null] = part.split('=');
@@ -172,6 +181,7 @@ class GrocyProxy
}
var vurl = ""
+ let value;
for ([key, value] of params)
{
vurl += "&" + key
diff --git a/js/viewjs/batteries.js b/js/viewjs/batteries.js
index 5c99e0ed..48e104a9 100644
--- a/js/viewjs/batteries.js
+++ b/js/viewjs/batteries.js
@@ -6,6 +6,12 @@
$scope = (scope) => $(scope).find(scope);
}
+ // preload some views.
+ top.on('load', () =>
+ {
+ Grocy.PreloadView("batteryform");
+ });
+
var batteriesTable = $scope('#batteries-table').DataTable({
'order': [[1, 'asc']],
'columnDefs': [
diff --git a/js/viewjs/batteriesoverview.js b/js/viewjs/batteriesoverview.js
index 59b59eba..ad7641c5 100644
--- a/js/viewjs/batteriesoverview.js
+++ b/js/viewjs/batteriesoverview.js
@@ -8,6 +8,13 @@
var batterycard = Grocy.Use("batterycard");
+ // preload some views.
+ top.on('load', () =>
+ {
+ Grocy.PreloadView("batteriesjournal");
+ Grocy.PreloadView("batteryform");
+ });
+
var batteriesOverviewTable = $scope('#batteries-overview-table').DataTable({
'order': [[4, 'asc']],
'columnDefs': [
diff --git a/js/viewjs/choresoverview.js b/js/viewjs/choresoverview.js
index ae821435..345ab438 100644
--- a/js/viewjs/choresoverview.js
+++ b/js/viewjs/choresoverview.js
@@ -10,6 +10,12 @@
var chorecard = Grocy.Use("chorecard");
+ // preload some views.
+ top.on('load', () =>
+ {
+ Grocy.PreloadView("choresjournal");
+ });
+
var choresOverviewTable = $scope('#chores-overview-table').DataTable({
'order': [[2, 'asc']],
'columnDefs': [
diff --git a/js/viewjs/locations.js b/js/viewjs/locations.js
index fb48d790..552d3d3b 100644
--- a/js/viewjs/locations.js
+++ b/js/viewjs/locations.js
@@ -6,6 +6,12 @@
$scope = (scope) => $(scope).find(scope);
}
+ // preload some views.
+ top.on('load', () =>
+ {
+ Grocy.PreloadView("locationform");
+ });
+
var locationsTable = $scope('#locations-table').DataTable({
'order': [[1, 'asc']],
'columnDefs': [
diff --git a/js/viewjs/productform.js b/js/viewjs/productform.js
index 7cecef37..2c0149cd 100644
--- a/js/viewjs/productform.js
+++ b/js/viewjs/productform.js
@@ -11,6 +11,13 @@ function productformView(Grocy, scope = null)
}
Grocy.Use("numberpicker");
+
+ // preload some views.
+ top.on('load', () =>
+ {
+ Grocy.PreloadView("productgroupform");
+ });
+
var shoppinglocationpicker = Grocy.Use("shoppinglocationpicker");
var userfields = Grocy.Use("userfieldsform");
var productpicker = Grocy.Use("productpicker");
diff --git a/js/viewjs/productgroups.js b/js/viewjs/productgroups.js
index b618cc3e..9b60d5a8 100644
--- a/js/viewjs/productgroups.js
+++ b/js/viewjs/productgroups.js
@@ -6,6 +6,10 @@
$scope = (scope) => $(scope).find(scope);
}
+ // preload some views.
+ Grocy.PreloadView("productgroupform");
+
+
var groupsTable = $scope('#productgroups-table').DataTable({
'order': [[1, 'asc']],
'columnDefs': [
diff --git a/js/viewjs/quantityunitform.js b/js/viewjs/quantityunitform.js
index 7db364ca..840c3025 100644
--- a/js/viewjs/quantityunitform.js
+++ b/js/viewjs/quantityunitform.js
@@ -10,6 +10,11 @@ function quantityunitformView(Grocy, scope = null)
var userfields = Grocy.Use("userfieldsform");
+ // preload some views.
+
+ Grocy.PreloadView("quantityunitconversionform");
+
+
$scope('.save-quantityunit-button').on('click', function(e)
{
e.preventDefault();
diff --git a/js/viewjs/shoppinglist.js b/js/viewjs/shoppinglist.js
index 866f43b2..5596c004 100644
--- a/js/viewjs/shoppinglist.js
+++ b/js/viewjs/shoppinglist.js
@@ -15,6 +15,12 @@ function shoppinglistView(Grocy, scope = null)
$scope = (scope) => $(scope).find(scope);
}
+ // preload some views.
+
+ Grocy.PreloadView("shoppinglistform");
+ Grocy.PreloadView("shoppinglistitemform");
+
+
Grocy.Use("calendarcard");
var productcard = Grocy.Use("productcard");
diff --git a/js/viewjs/shoppinglocations.js b/js/viewjs/shoppinglocations.js
index 7b866aeb..d165b08b 100644
--- a/js/viewjs/shoppinglocations.js
+++ b/js/viewjs/shoppinglocations.js
@@ -6,6 +6,11 @@
$scope = (scope) => $(scope).find(scope);
}
+ // preload some views.
+
+ Grocy.PreloadView("shoppinglocationform");
+
+
var locationsTable = $scope('#shoppinglocations-table').DataTable({
'order': [[1, 'asc']],
'columnDefs': [
diff --git a/js/viewjs/stockentries.js b/js/viewjs/stockentries.js
index 667fb77c..ede85e9b 100644
--- a/js/viewjs/stockentries.js
+++ b/js/viewjs/stockentries.js
@@ -11,6 +11,19 @@
var productcard = Grocy.Use("productcard");
var productpicker = Grocy.Use("productpicker");
+ // preload some views.
+ Grocy.PreloadView("stockentryform");
+ Grocy.PreloadView("shoppinglistitemform");
+ Grocy.PreloadView("purchase");
+ Grocy.PreloadView("conusme");
+ Grocy.PreloadView("inventory");
+ Grocy.PreloadView("stockjournal");
+ Grocy.PreloadView("stockjournalsummary");
+
+ if (Grocy.FeatureFlags.GROCY_FEATURE_FLAG_STOCK_LOCATION_TRACKING)
+ Grocy.PreloadView("transfer");
+
+
var stockEntriesTable = $scope('#stockentries-table').DataTable({
'order': [[2, 'asc']],
'columnDefs': [
diff --git a/js/viewjs/stockoverview.js b/js/viewjs/stockoverview.js
index 0d036db1..250bbfd7 100755
--- a/js/viewjs/stockoverview.js
+++ b/js/viewjs/stockoverview.js
@@ -9,6 +9,19 @@
var productcard = Grocy.Use("productcard");
+ // preload some views.
+
+ Grocy.PreloadView("stockentries");
+ Grocy.PreloadView("shoppinglistitemform");
+ Grocy.PreloadView("purchase");
+ Grocy.PreloadView("conusme");
+ Grocy.PreloadView("inventory");
+ Grocy.PreloadView("stockjournal");
+ Grocy.PreloadView("stockjournalsummary");
+
+ if (Grocy.FeatureFlags.GROCY_FEATURE_FLAG_STOCK_LOCATION_TRACKING)
+ Grocy.PreloadView("transfer");
+
var stockOverviewTable = $scope('#stock-overview-table').DataTable({
'order': [[5, 'asc']],
'columnDefs': [
diff --git a/js/viewjs/taskcategories.js b/js/viewjs/taskcategories.js
index f45af240..e0fc8aef 100644
--- a/js/viewjs/taskcategories.js
+++ b/js/viewjs/taskcategories.js
@@ -6,6 +6,11 @@
$scope = (scope) => $(scope).find(scope);
}
+ // preload some views.
+
+ Grocy.PreloadView("taskcategoryform");
+
+
var categoriesTable = $scope('#taskcategories-table').DataTable({
'order': [[1, 'asc']],
'columnDefs': [
diff --git a/js/viewjs/tasks.js b/js/viewjs/tasks.js
index 9c13597d..52c1674b 100644
--- a/js/viewjs/tasks.js
+++ b/js/viewjs/tasks.js
@@ -8,6 +8,10 @@
$scope = (scope) => $(scope).find(scope);
}
+ // preload some views.
+ Grocy.PreloadView("taskform");
+
+
var tasksTable = $scope('#tasks-table').DataTable({
'order': [[2, 'asc']],
'columnDefs': [
diff --git a/js/viewjs/userentities.js b/js/viewjs/userentities.js
index 8920222b..e0ce6202 100644
--- a/js/viewjs/userentities.js
+++ b/js/viewjs/userentities.js
@@ -5,6 +5,9 @@
{
$scope = (scope) => $(scope).find(scope);
}
+ // preload some views.
+ Grocy.PreloadView("userentityform")
+
var userentitiesTable = $scope('#userentities-table').DataTable({
'order': [[1, 'asc']],
diff --git a/js/viewjs/userfields.js b/js/viewjs/userfields.js
index bd944152..8a7b7570 100644
--- a/js/viewjs/userfields.js
+++ b/js/viewjs/userfields.js
@@ -6,6 +6,10 @@
$scope = (scope) => $(scope).find(scope);
}
+ // preload some views.
+ Grocy.PreloadView("userfieldform");
+
+
var userfieldsTable = $scope('#userfields-table').DataTable({
'order': [[1, 'asc']],
'columnDefs': [
diff --git a/js/viewjs/userobjects.js b/js/viewjs/userobjects.js
index f4d6f65b..f5a0dc80 100644
--- a/js/viewjs/userobjects.js
+++ b/js/viewjs/userobjects.js
@@ -6,6 +6,10 @@
$scope = (scope) => $(scope).find(scope);
}
+ // preload some views.
+ Grocy.PreloadView("userobjectform");
+
+
var userobjectsTable = $scope('#userobjects-table').DataTable({
'order': [[1, 'asc']],
'columnDefs': [
diff --git a/package.json b/package.json
index 6485aa69..d6997858 100644
--- a/package.json
+++ b/package.json
@@ -13,7 +13,7 @@
"@fullcalendar/timegrid": "4.4.2",
"@rollup/plugin-eslint": "^8.0.1",
"animate.css": "^3.7.2",
- "bootbox": "^5.3.2",
+ "bootbox": "^5.5.2",
"bootstrap": "^4.5.2",
"bootstrap-select": "^1.13.18",
"bwip-js": "^3.0.1",
diff --git a/yarn.lock b/yarn.lock
index fb668165..1d704cb3 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1847,7 +1847,7 @@ __metadata:
languageName: node
linkType: hard
-"bootbox@npm:^5.3.2":
+"bootbox@npm:^5.5.2":
version: 5.5.2
resolution: "bootbox@npm:5.5.2"
dependencies:
@@ -4709,7 +4709,7 @@ fsevents@~2.3.2:
autoprefixer: ^10.2.6
babel-core: ^6.26.3
babel-preset-es2015: ^6.24.1
- bootbox: ^5.3.2
+ bootbox: ^5.5.2
bootstrap: ^4.5.2
bootstrap-select: ^1.13.18
browserslist: ^4.16.6