update
This commit is contained in:
@@ -1,207 +0,0 @@
|
||||
/**
|
||||
* taggcodeApp.js
|
||||
* Dynamische AssetMenu implementatie met TagcodeApp API
|
||||
* Vervangt de statische assetData met calls naar REST-endpoints.
|
||||
*/
|
||||
|
||||
class TagcodeApp {
|
||||
constructor(baseURL = 'https://pimmoerman.nl/rdlab/tagcode.app/v2.1/api') {
|
||||
this.baseURL = baseURL;
|
||||
}
|
||||
|
||||
async fetchData(path, params = {}) {
|
||||
const url = new URL(`${this.baseURL}/${path}`);
|
||||
Object.entries(params).forEach(([key, value]) => {
|
||||
url.searchParams.append(key, value);
|
||||
});
|
||||
const response = await fetch(url);
|
||||
if (!response.ok) throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
||||
const json = await response.json();
|
||||
if (!json.success) throw new Error(json.error || json.message);
|
||||
return json.data;
|
||||
}
|
||||
|
||||
// Asset endpoints
|
||||
getAllAssets() {
|
||||
return this.fetchData('asset/get_all_assets.php');
|
||||
}
|
||||
|
||||
getAssetDetail(tag_code) {
|
||||
return this.fetchData('asset/get_detail_asset.php', { tag_code });
|
||||
}
|
||||
|
||||
getAssetHistory(asset_tag_number) {
|
||||
return this.fetchData('asset/get_history_asset.php', { asset_tag_number });
|
||||
}
|
||||
|
||||
getAssetHierarchy(asset_tag_number) {
|
||||
return this.fetchData('asset/get_asset_hierarchy.php', { asset_tag_number });
|
||||
}
|
||||
|
||||
createOrUpdateAsset(params) {
|
||||
// Bij create/update worden alle velden via query params meegegeven
|
||||
return this.fetchData('asset/create_asset.php', params);
|
||||
}
|
||||
|
||||
// Product & vendor endpoints
|
||||
getVendors() {
|
||||
return this.fetchData('vendor/get_vendors.php');
|
||||
}
|
||||
|
||||
getSubtypes(vendor_name) {
|
||||
return this.fetchData('product/get_subtypesFromVendor.php', { vendor_name });
|
||||
}
|
||||
|
||||
getProductModels(vendor_name, product_subtype_name) {
|
||||
return this.fetchData('product/get_product_models.php', { vendor_name, product_subtype_name });
|
||||
}
|
||||
|
||||
getLocations() {
|
||||
return this.fetchData('location/get_locations.php');
|
||||
}
|
||||
}
|
||||
|
||||
class DynamicAssetMenu {
|
||||
constructor(nodeName, api = new TagcodeApp()) {
|
||||
this.nodeName = nodeName;
|
||||
this.api = api;
|
||||
this.data = {
|
||||
vendors: [],
|
||||
subtypes: {}, // per vendor
|
||||
models: {} // per vendor+subtype
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialiseer: haal vendors en locaties eenmalig op
|
||||
*/
|
||||
async init() {
|
||||
this.data.vendors = await this.api.getVendors();
|
||||
this.data.locations = await this.api.getLocations();
|
||||
}
|
||||
|
||||
/**
|
||||
* Injecteer HTML, data en events
|
||||
*/
|
||||
getClientInitCode() {
|
||||
const node = this.nodeName;
|
||||
return `
|
||||
// --- DynamicAssetMenu voor ${node} ---
|
||||
window.TagcodeApp = window.TagcodeApp || ${TagcodeApp.toString()};
|
||||
window.assetAPI = window.assetAPI || new TagcodeApp();
|
||||
|
||||
// Helper populate
|
||||
function populate(el, opts, sel) {
|
||||
const old = el.value;
|
||||
el.innerHTML = '<option value="">Select…</option>';
|
||||
(opts||[]).forEach(o=>{
|
||||
const opt = document.createElement('option');
|
||||
opt.value = o; opt.textContent = o;
|
||||
el.appendChild(opt);
|
||||
});
|
||||
el.value = sel || '';
|
||||
if (el.value !== old) el.dispatchEvent(new Event('change'));
|
||||
}
|
||||
|
||||
// InitEditor
|
||||
window.EVOLV.nodes.${node}.assetMenu.initEditor = async function(node) {
|
||||
this.injectHtml();
|
||||
// eerst: laad vendor-lijst
|
||||
const vendors = await window.assetAPI.getVendors();
|
||||
const vendorNames = vendors.map(v=>v.name);
|
||||
populate(document.getElementById('node-input-supplier'), vendorNames, node.supplier);
|
||||
|
||||
// wire events
|
||||
const elems = {
|
||||
supplier: document.getElementById('node-input-supplier'),
|
||||
category: document.getElementById('node-input-category'),
|
||||
type: document.getElementById('node-input-assetType'),
|
||||
model: document.getElementById('node-input-model'),
|
||||
unit: document.getElementById('node-input-unit')
|
||||
};
|
||||
|
||||
elems.supplier.addEventListener('change', async ()=>{
|
||||
const v = elems.supplier.value;
|
||||
if (!v) return populate(elems.category, [], '');
|
||||
const subs = await window.assetAPI.getSubtypes(v);
|
||||
const names = subs.map(s=>s.name);
|
||||
populate(elems.category, names, node.category);
|
||||
});
|
||||
|
||||
elems.category.addEventListener('change', async ()=>{
|
||||
const v = elems.supplier.value, c = elems.category.value;
|
||||
if (!v||!c) return populate(elems.type, [], '');
|
||||
const models = await window.assetAPI.getProductModels(v, c);
|
||||
window._currentModels = models; // tijdelijk cachen
|
||||
const types = Array.from(new Set(models.map(m=>m.product_model_type)));
|
||||
populate(elems.type, types, node.assetType);
|
||||
});
|
||||
|
||||
elems.type.addEventListener('change', ()=>{
|
||||
const t = elems.type.value;
|
||||
const models = window._currentModels || [];
|
||||
const filtered = models.filter(m=>m.product_model_type===t);
|
||||
const names = filtered.map(m=>m.name);
|
||||
window._filteredModels = filtered;
|
||||
populate(elems.model, names, node.model);
|
||||
});
|
||||
|
||||
elems.model.addEventListener('change', ()=>{
|
||||
const m = elems.model.value;
|
||||
const models = window._filteredModels || [];
|
||||
const entry = models.find(x=>x.name===m);
|
||||
const units = entry && entry.product_model_meta ? Object.keys(entry.product_model_meta) : [];
|
||||
populate(elems.unit, units, node.unit);
|
||||
});
|
||||
|
||||
// laadt opgeslagen waarden
|
||||
if (node.supplier) elems.supplier.dispatchEvent(new Event('change'));
|
||||
};
|
||||
`;
|
||||
}
|
||||
|
||||
getHtmlTemplate() {
|
||||
return `
|
||||
<!-- Asset Properties -->
|
||||
<hr />
|
||||
<h3>Asset selection</h3>
|
||||
<div class="form-row">
|
||||
<label for="node-input-supplier"><i class="fa fa-industry"></i> Supplier</label>
|
||||
<select id="node-input-supplier" style="width:70%;"></select>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-category"><i class="fa fa-sitemap"></i> Category</label>
|
||||
<select id="node-input-category" style="width:70%;"></select>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-assetType"><i class="fa fa-puzzle-piece"></i> Type</label>
|
||||
<select id="node-input-assetType" style="width:70%;"></select>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-model"><i class="fa fa-wrench"></i> Model</label>
|
||||
<select id="node-input-model" style="width:70%;"></select>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-unit"><i class="fa fa-balance-scale"></i> Unit</label>
|
||||
<select id="node-input-unit" style="width:70%;"></select>
|
||||
</div>
|
||||
<hr />
|
||||
`;
|
||||
}
|
||||
|
||||
getHtmlInjectionCode() {
|
||||
const tmpl = this.getHtmlTemplate().replace(/`/g, '\\`').replace(/\$/g, '\\\$');
|
||||
return `
|
||||
// Asset HTML injection voor ${this.nodeName}
|
||||
window.EVOLV.nodes.${this.nodeName}.assetMenu.injectHtml = function() {
|
||||
const placeholder = document.getElementById('asset-fields-placeholder');
|
||||
if (placeholder && !placeholder.hasChildNodes()) {
|
||||
placeholder.innerHTML = \`${tmpl}\`;
|
||||
}
|
||||
};
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
// Exporteer voor gebruik in Node-RED
|
||||
module.exports = { TagcodeApp, DynamicAssetMenu };
|
||||
Reference in New Issue
Block a user