grocy/js/lib/proxy.js
2021-06-23 15:41:18 +02:00

184 lines
4.3 KiB
JavaScript

import { GrocyFrontendHelpers } from '../helpers/frontend';
import * as components from '../components';
class GrocyProxy
{
constructor(RootGrocy, scopeSelector, config, url)
{
this.rootGrocy = RootGrocy;
// proxy-local members, because they might not be set globally.
this.QuantityUnits = config.QuantityUnits;
this.QuantityUnitConversionsResolved = config.QuantityUnitConversionsResolved || [];
this.QuantityUnitEditFormRedirectUri = config.QuantityUnitEditFormRedirectUri;
this.MealPlanFirstDayOfWeek = config.MealPlanFirstDayOfWeek;
this.EditMode = config.EditMode;
this.EditObjectId = config.EditObjectId;
this.DefaultMinAmount = config.DefaultMinAmount;
this.UserPictureFileName = config.UserPictureFileName;
this.EditObjectParentId = config.EditObjectParentId;
this.EditObjectParentName = config.EditObjectParentName;
this.EditObject = config.EditObject;
this.EditObjectProduct = config.EditObjectProduct;
this.RecipePictureFileName = config.RecipePictureFileName;
this.InstructionManualFileNameName = config.InstructionManualFileNameName;
// components are always local
this.Components = {};
this.initComponents = [];
// scoping
this.scopeSelector = scopeSelector;
this.scope = $(scope);
this.$scope = this.scope.find;
var queryString = url.split('?', 2);
this.virtualUrl = queryString.length == 2 ? queryString[1] : ""; // maximum two parts
this.config = config;
// scoped variants of some helpers
this.FrontendHelpers = new GrocyFrontendHelpers(this, this.Api, this.scopeSelector);
this.configProxy = Proxy.revocable(this.config, {
get: function(target, prop, receiver)
{
if (Object.prototype.hasOwnProperty.call(target, prop))
{
return Reflect.get(...arguments);
}
else
{
return Reflect.get(rootGrocy.config, prop, target);
}
}
})
// This is where the magic happens!
// basically, this Proxy object checks if a member
// is defined in this proxy class, and returns it
// if so.
// If not, the prop is handed over to the root
// grocy instance.
this.grocyProxy = Proxy.revocable(this, {
get: function(target, prop, receiver)
{
if (Object.prototype.hasOwnProperty.call(target, prop))
{
return Reflect.get(...arguments)
}
else
{
return Reflect.get(RootGrocy, prop, receiver);
}
}
});
}
Unload()
{
this.grocyProxy.revoke();
this.configProxy.revoke();
}
Use(componentName)
{
// initialize Components only once
if (this.initComponents.find(elem => elem == componentName))
return;
if (Object.prototype.hasOwnProperty.call(components, componentName))
{
// add-then-init to resolve circular dependencies
this.initComponents.push(componentName);
var component = components[componentName](this, this.scopeSelector);
this.components[component.key] = component;
}
else
{
console.error("Unable to find component " + componentName);
}
}
LoadView(viewName)
{
if (Object.prototype.hasOwnProperty.call(window, viewName + "View"))
{
window[viewName + "View"](this, this.scopeSelector);
}
}
// URI params on integrated components don't work because they
// don't have an URL. So let's fake it.
GetUriParam(key)
{
var currentUri = this.virtualUrl;
var vars = currentUri.split('&');
for (var i = 0; i < vars.length; i++)
{
var currentParam = vars[i].split('=');
if (currentParam[0] === key)
{
return currentParam[1] === undefined ? true : decodeURIComponent(currentParam[1]);
}
}
}
UpdateUriParam(key, value)
{
params = {}
var vars = this.virtualUrl.split("&");
for (part of vars)
{
var lkey, lvalue;
[lkey, lvalue = null] = part.split('=');
params[lkey] = lvalue;
}
params[key] = value;
var vurl = ""
for ([key, value] of params)
{
vurl += "&" + key
if (value != null)
{
vurl += '=' + encodeURIComponent(value);
}
}
this.virtualUrl = vurl.substring(1); // remove leading &
}
RemoveUriParam(key)
{
params = {}
var vars = this.virtualUrl.split("&");
for (part of vars)
{
var lkey, lvalue;
[lkey, lvalue = null] = part.split('=');
if (lkey == key)
continue;
params[lkey] = lvalue;
}
var vurl = ""
for ([key, value] of params)
{
vurl += "&" + key
if (value != null)
{
vurl += '=' + encodeURIComponent(value);
}
}
this.virtualUrl = vurl.substring(1); // remove leading &
}
}