fill out api.js with stubs later assigned in modules
This commit is contained in:
parent
b917bfa1df
commit
e506d75b63
10 changed files with 181 additions and 166 deletions
|
|
@ -239,8 +239,16 @@ gapp.register("kiri-mode.cam.tools", (root, exports) => {
|
|||
};
|
||||
ui.toolCopy.onclick = function() {
|
||||
let clone = Object.assign({}, selectedTool);
|
||||
let { name } = clone;
|
||||
let split = name.split(' ');
|
||||
let endv = parseInt(split.pop());
|
||||
if (endv) {
|
||||
name = split.join(' ') + ' ' + (endv + 1);
|
||||
} else {
|
||||
name = `${name} 2`;
|
||||
}
|
||||
clone.number = maxTool + 1;
|
||||
clone.name = `${clone.name} copy`;
|
||||
clone.name = name;
|
||||
editTools.push(clone);
|
||||
setToolChanged(true);
|
||||
renderTools();
|
||||
|
|
|
|||
|
|
@ -432,15 +432,6 @@ FDM.export = function(print, online, ondone, ondebug) {
|
|||
}
|
||||
|
||||
function moveTo(newpos, rate, comment) {
|
||||
if (pingRemain) {
|
||||
if (newpos.e) {
|
||||
if (pingRemain - newpos.e < -0.4) {
|
||||
// split move if ping over-extrudes? complicates emitted calc.
|
||||
// console.log({over_ping: pingRemain - newpos.e});
|
||||
}
|
||||
pingRemain -= newpos.e;
|
||||
}
|
||||
}
|
||||
let o = [!rate && !newpos.e ? 'G0' : 'G1'];
|
||||
let emit = { x: false, y: false, z: false };
|
||||
if (typeof newpos.x === 'number' && newpos.x !== pos.x) {
|
||||
|
|
@ -518,9 +509,6 @@ FDM.export = function(print, online, ondone, ondebug) {
|
|||
totaldistance += o1.point.distTo2D(o2.point);
|
||||
}, 1);
|
||||
|
||||
// for palette pings, amount of extrusion left
|
||||
let pingRemain = 0;
|
||||
|
||||
// retract before first move
|
||||
retract();
|
||||
|
||||
|
|
|
|||
208
src/kiri/api.js
208
src/kiri/api.js
|
|
@ -6,59 +6,126 @@
|
|||
// dep: data.local
|
||||
// dep: kiri.utils
|
||||
// dep: kiri.consts
|
||||
gapp.register("kiri.api", [], (root, exports) => {
|
||||
gapp.register("kiri.api", (root, exports) => {
|
||||
|
||||
const { data, kiri, noop } = root;
|
||||
const { consts, utils } = kiri;
|
||||
const { areEqual, parseOpt, encodeOpt, ajax, o2js, js2o } = utils;
|
||||
const { LISTS } = consts;
|
||||
|
||||
let isHover = false;
|
||||
|
||||
const feature = {
|
||||
seed: true, // seed profiles on first use
|
||||
meta: true, // show selected widget metadata
|
||||
frame: true, // receive frame events
|
||||
alert_event: false, // emit alerts as events instead of display
|
||||
controls: true, // show or not side menus
|
||||
device_filter: undefined, // function to limit devices shown
|
||||
drop_group: undefined, // optional array to group multi drop
|
||||
drop_layout: true, // layout on new drop
|
||||
hoverAdds: false, // when true only searches widget additions
|
||||
on_key: undefined, // function override default key handlers
|
||||
on_load: undefined, // function override file drop loads
|
||||
on_add_stl: undefined, // legacy override stl drop loads
|
||||
on_mouse_up: undefined, // function intercepts mouse up select
|
||||
on_mouse_down: undefined, // function intercepts mouse down
|
||||
work_alerts: true, // allow disabling work progress alerts
|
||||
modes: [ "fdm", "sla", "cam", "laser" ], // enable device modes
|
||||
pmode: consts.PMODES.SPEED, // preview modes
|
||||
// hover: false, // when true fires mouse hover events
|
||||
get hover() {
|
||||
return isHover;
|
||||
let { data, kiri, moto, noop } = root,
|
||||
{ consts, utils } = kiri,
|
||||
{ ajax, o2js, js2o } = utils,
|
||||
lists = consts.LISTS,
|
||||
clone = Object.clone,
|
||||
isHover = false,
|
||||
feature = {
|
||||
seed: true, // seed profiles on first use
|
||||
meta: true, // show selected widget metadata
|
||||
frame: true, // receive frame events
|
||||
alert_event: false, // emit alerts as events instead of display
|
||||
controls: true, // show or not side menus
|
||||
device_filter: undefined, // function to limit devices shown
|
||||
drop_group: undefined, // optional array to group multi drop
|
||||
drop_layout: true, // layout on new drop
|
||||
hoverAdds: false, // when true only searches widget additions
|
||||
on_key: undefined, // function override default key handlers
|
||||
on_load: undefined, // function override file drop loads
|
||||
on_add_stl: undefined, // legacy override stl drop loads
|
||||
on_mouse_up: undefined, // function intercepts mouse up select
|
||||
on_mouse_down: undefined, // function intercepts mouse down
|
||||
work_alerts: true, // allow disabling work progress alerts
|
||||
pmode: consts.PMODES.SPEED, // preview modes
|
||||
// hover: false, // when true fires mouse hover events
|
||||
get hover() {
|
||||
return isHover;
|
||||
},
|
||||
set hover(b) {
|
||||
isHover = b;
|
||||
moto.broker.publish("feature.hover", b);
|
||||
}
|
||||
},
|
||||
set hover(b) {
|
||||
isHover = b;
|
||||
moto.broker.publish("feature.hover", b);
|
||||
}
|
||||
};
|
||||
doit = {
|
||||
undo: noop, // do.js
|
||||
redo: noop // do.js
|
||||
},
|
||||
devel = {
|
||||
xray(layers, raw) {
|
||||
let proc = api.conf.get().process,
|
||||
size = proc.sliceHeight || proc.slaSlice || 1,
|
||||
base = (proc.firstSliceHeight || size);
|
||||
layers = Array.isArray(layers) ? layers : [ layers ];
|
||||
proc.xray = layers.map(l => raw ? l : base + l * size - size / 2);
|
||||
proc.xrayi = layers.slice();
|
||||
api.function.slice();
|
||||
}
|
||||
},
|
||||
local = {
|
||||
get: (key) => localGet(key),
|
||||
getInt: (key) => parseInt(localGet(key)),
|
||||
getFloat: (key) => parseFloat(localGet(key)),
|
||||
getBoolean: (key, def = true) => {
|
||||
let val = localGet(key);
|
||||
return val === true || val === 'true' || val === def;
|
||||
},
|
||||
toggle: (key, val, def) => localSet(key, val ?? !api.local.getBoolean(key, def)),
|
||||
put: (key, val) => localSet(key, val),
|
||||
set: (key, val) => localSet(key, val),
|
||||
},
|
||||
tweak = {
|
||||
line_precision(v) { api.work.config({base:{clipperClean: v}}) },
|
||||
gcode_decimals(v) { api.work.config({base:{gcode_decimals: v}}) }
|
||||
},
|
||||
und = undefined,
|
||||
api = exports({
|
||||
ajax, // via utils
|
||||
busy: {}, // main.js
|
||||
catalog: und, // main.js
|
||||
clip, // <--
|
||||
clone, // <--
|
||||
color: und, // main.js
|
||||
conf: {}, // settings.js
|
||||
const: {}, // main.js
|
||||
dialog: {}, // main.js
|
||||
doit, // <--
|
||||
devel, // <--
|
||||
event: {}, // main.js
|
||||
feature, // <--
|
||||
focus: noop,
|
||||
function: {}, // function.js
|
||||
group: {}, // main.js
|
||||
help: {}, // main.js
|
||||
hide: {}, // main.js
|
||||
image: {}, // main.js
|
||||
js2o, // via utils
|
||||
language: und, // main.js
|
||||
local, // <--
|
||||
lists, // <--
|
||||
modal: {}, // main.js
|
||||
mode: {}, // main.js
|
||||
o2js, // via utils
|
||||
platform: {}, // platform.js
|
||||
probe: {}, // main.js
|
||||
process: {}, // main.js
|
||||
sdb: data.local,
|
||||
selection: {}, // selection.js
|
||||
settings: {}, // settings.js
|
||||
show: {}, // main.js
|
||||
space: {}, // main.js
|
||||
uc: {}, // main.js
|
||||
ui: {}, // main.js
|
||||
util: {}, // main.js
|
||||
var: {
|
||||
layer_lo: 0,
|
||||
layer_hi: 0,
|
||||
layer_max: 0
|
||||
},
|
||||
view: {}, // main.js
|
||||
tweak,
|
||||
widgets: {}, // widgets.js
|
||||
work: und, // main.js
|
||||
});
|
||||
|
||||
const devel = {
|
||||
xray: (layers, raw) => {
|
||||
let proc = api.conf.get().process;
|
||||
let size = proc.sliceHeight || proc.slaSlice || 1;
|
||||
let base = (proc.firstSliceHeight || size);
|
||||
layers = Array.isArray(layers) ? layers : [ layers ];
|
||||
proc.xray = layers.map(l => raw ? l : base + l * size - size / 2);
|
||||
proc.xrayi = layers.slice();
|
||||
api.function.slice();
|
||||
}
|
||||
};
|
||||
|
||||
const tweak = {
|
||||
line_precision(v) { api.work.config({base:{clipperClean: v}}) },
|
||||
gcode_decimals(v) { api.work.config({base:{gcode_decimals: v}}) }
|
||||
};
|
||||
function clip(text) {
|
||||
navigator.clipboard
|
||||
.writeText(text)
|
||||
.catch(err => console.error('Clipboard Error:', err));
|
||||
}
|
||||
|
||||
function localGet(key) {
|
||||
let sloc = api.conf.get().local;
|
||||
|
|
@ -71,45 +138,4 @@ function localSet(key, val) {
|
|||
return val;
|
||||
}
|
||||
|
||||
const api = exports({
|
||||
ajax: ajax,
|
||||
doit: {
|
||||
undo: noop, // set in do.js
|
||||
redo: noop // set in do.js
|
||||
},
|
||||
clip: (text) => {
|
||||
navigator.clipboard
|
||||
.writeText(text)
|
||||
.catch(err => console.error('Clipboard Error:', err));
|
||||
},
|
||||
clone: Object.clone,
|
||||
devel,
|
||||
feature,
|
||||
js2o: js2o,
|
||||
local: {
|
||||
get: (key) => localGet(key),
|
||||
getInt: (key) => parseInt(localGet(key)),
|
||||
getFloat: (key) => parseFloat(localGet(key)),
|
||||
getBoolean: (key, def = true) => {
|
||||
let val = localGet(key);
|
||||
return val === true || val === 'true' || val === def;
|
||||
},
|
||||
toggle: (key, val, def) => localSet(key, val ?? !api.local.getBoolean(key, def)),
|
||||
put: (key, val) => localSet(key, val),
|
||||
set: (key, val) => localSet(key, val),
|
||||
},
|
||||
lists: LISTS,
|
||||
o2js: o2js,
|
||||
sdb: data.local,
|
||||
show: {},
|
||||
uc: {},
|
||||
ui: {},
|
||||
var: {
|
||||
layer_lo: 0,
|
||||
layer_hi: 0,
|
||||
layer_max: 0
|
||||
},
|
||||
tweak,
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
// dep: kiri-mode.drag.driver
|
||||
// dep: kiri-mode.wjet.driver
|
||||
// dep: kiri-mode.wedm.driver
|
||||
gapp.register("kiri.function", [], (root, exports) => {
|
||||
gapp.register("kiri.function", (root, exports) => {
|
||||
|
||||
const { kiri } = root;
|
||||
const { api, client, consts, utils } = kiri;
|
||||
|
|
@ -439,7 +439,7 @@ function parseCode(code, type) {
|
|||
}
|
||||
|
||||
// extend API (api.function)
|
||||
const functions = api.function = {
|
||||
const functions = Object.assign(api.function, {
|
||||
slice: prepareSlices,
|
||||
print: preparePreview,
|
||||
prepare: preparePreview,
|
||||
|
|
@ -449,6 +449,6 @@ const functions = api.function = {
|
|||
parse: parseCode,
|
||||
clear: client.clear,
|
||||
clear_progress() { complete = {} }
|
||||
};
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
|||
|
|
@ -772,10 +772,10 @@ gapp.register("kiri.init", (root, exports) => {
|
|||
|
||||
// MAIN INITIALIZATION FUNCTION
|
||||
function init_one() {
|
||||
let { event, conf, view, show } = api;
|
||||
let { bound, toInt, toFloat } = uc;
|
||||
let { newBlank, newButton, newBoolean, newGroup, newInput } = uc;
|
||||
let { newSelect, newText, newRow, newGCode, newDiv } = uc;
|
||||
let { event, conf, view, show } = api,
|
||||
{ bound, toInt, toFloat } = uc,
|
||||
{ newBlank, newButton, newBoolean, newGroup, newInput } = uc,
|
||||
{ newSelect, newText, newRow, newGCode, newDiv } = uc;
|
||||
|
||||
event.emit('init.one');
|
||||
|
||||
|
|
@ -783,7 +783,6 @@ gapp.register("kiri.init", (root, exports) => {
|
|||
conf.restore();
|
||||
|
||||
let container = $('container'),
|
||||
welcome = $('welcome'),
|
||||
gcode = $('dev-gcode'),
|
||||
tracker = $('tracker'),
|
||||
controller = settings().controller;
|
||||
|
|
|
|||
|
|
@ -50,65 +50,65 @@ gapp.register("kiri.main", (root, exports) => {
|
|||
DRIVER = undefined,
|
||||
viewMode = VIEWS.ARRANGE,
|
||||
autoSaveTimer = null,
|
||||
busy = 0;
|
||||
busy = 0,
|
||||
{ assign } = Object;
|
||||
|
||||
// extend API
|
||||
Object.assign(api, {
|
||||
ui: UI = Object.assign(api.ui, UI),
|
||||
uc: UC = Object.assign(api.uc, UC),
|
||||
assign(api, {
|
||||
ui: UI = assign(api.ui, UI),
|
||||
uc: UC = assign(api.uc, UC),
|
||||
stats,
|
||||
focus: noop,
|
||||
catalog: FILES,
|
||||
busy: {
|
||||
busy: assign(api.busy, {
|
||||
val() { return busy },
|
||||
inc() { kiri.api.event.emit("busy", ++busy) },
|
||||
dec() { kiri.api.event.emit("busy", --busy) }
|
||||
},
|
||||
}),
|
||||
color: COLOR,
|
||||
const: {
|
||||
const: assign(api.const, {
|
||||
LANG,
|
||||
LOCAL,
|
||||
SETUP,
|
||||
SECURE,
|
||||
STACKS,
|
||||
},
|
||||
dialog: {
|
||||
}),
|
||||
dialog: assign(api.dialog, {
|
||||
show: showModal,
|
||||
hide: hideModal,
|
||||
update_process_list: updateProcessList
|
||||
},
|
||||
help: {
|
||||
}),
|
||||
help: assign(api.help, {
|
||||
show: showHelp,
|
||||
file: showHelpFile
|
||||
},
|
||||
event: {
|
||||
}),
|
||||
event: assign(api.event, {
|
||||
on(t,l) { return EVENT.on(t,l) },
|
||||
emit(t,m,o) { return EVENT.publish(t,m,o) },
|
||||
bind(t,m,o) { return EVENT.bind(t,m,o) },
|
||||
alerts(clr) { api.alerts.update(clr) },
|
||||
import: loadFile,
|
||||
settings: triggerSettingsEvent
|
||||
},
|
||||
group: {
|
||||
}),
|
||||
group: assign(api.group, {
|
||||
merge: groupMerge,
|
||||
split: groupSplit,
|
||||
},
|
||||
hide: {
|
||||
}),
|
||||
hide: assign(api.hide, {
|
||||
alert(rec, recs) { api.alerts.hide(...arguments) },
|
||||
import: noop,
|
||||
slider: hideSlider
|
||||
},
|
||||
image: {
|
||||
}),
|
||||
image: assign(api.image, {
|
||||
dialog: loadImageDialog,
|
||||
convert: loadImageConvert
|
||||
},
|
||||
}),
|
||||
language: kiri.lang,
|
||||
modal: {
|
||||
modal: assign(api.modal, {
|
||||
show: showModal,
|
||||
hide: hideModal,
|
||||
visible: modalShowing
|
||||
},
|
||||
mode: {
|
||||
}),
|
||||
mode: assign(api.mode, {
|
||||
get_id() { return MODE },
|
||||
get_lower: getModeLower,
|
||||
get: getMode,
|
||||
|
|
@ -128,17 +128,17 @@ gapp.register("kiri.main", (root, exports) => {
|
|||
api.mode.is_wjet() ||
|
||||
api.mode.is_laser()
|
||||
}
|
||||
},
|
||||
probe: {
|
||||
}),
|
||||
probe: assign(api.probe, {
|
||||
live: "https://live.grid.space",
|
||||
grid: noop,
|
||||
local: noop
|
||||
},
|
||||
process: {
|
||||
}),
|
||||
process: assign(api.process, {
|
||||
code: currentProcessCode,
|
||||
get: currentProcessName
|
||||
},
|
||||
show: Object.assign({
|
||||
}),
|
||||
show: assign(api.show, {
|
||||
alert() { return api.alerts.show(...arguments) },
|
||||
progress: setProgress,
|
||||
controls: setControlsVisible,
|
||||
|
|
@ -146,8 +146,8 @@ gapp.register("kiri.main", (root, exports) => {
|
|||
layer: setVisibleLayer,
|
||||
local: showLocal,
|
||||
import: function() { UI.import.style.display = '' }
|
||||
}, api.show),
|
||||
space: {
|
||||
}),
|
||||
space: assign(api.space, {
|
||||
reload,
|
||||
auto_save,
|
||||
restore: restoreWorkspace,
|
||||
|
|
@ -156,16 +156,16 @@ gapp.register("kiri.main", (root, exports) => {
|
|||
set_focus: setFocus,
|
||||
update: SPACE.update,
|
||||
is_dark() { return settings.ctrl().dark }
|
||||
},
|
||||
util: {
|
||||
}),
|
||||
util: assign(api.util, {
|
||||
isSecure,
|
||||
download: downloadBlob,
|
||||
ui2rec() { api.conf.update_from(...arguments) },
|
||||
rec2ui() { api.conf.update_fields(...arguments) },
|
||||
b64enc(obj) { return base64js.fromByteArray(new TextEncoder().encode(JSON.stringify(obj))) },
|
||||
b64dec(obj) { return JSON.parse(new TextDecoder().decode(base64js.toByteArray(obj))) }
|
||||
},
|
||||
view: {
|
||||
}),
|
||||
view: assign(api.view, {
|
||||
get() { return viewMode },
|
||||
set() { setViewMode(...arguments) },
|
||||
set_arrange() { api.view.set(VIEWS.ARRANGE) },
|
||||
|
|
@ -185,7 +185,7 @@ gapp.register("kiri.main", (root, exports) => {
|
|||
edges: setEdges,
|
||||
unit_scale: unitScale,
|
||||
wireframe: setWireframe,
|
||||
},
|
||||
}),
|
||||
work: kiri.client
|
||||
});
|
||||
|
||||
|
|
@ -426,11 +426,6 @@ gapp.register("kiri.main", (root, exports) => {
|
|||
api.var.layer_hi = layer;
|
||||
api.event.emit("slider.label");
|
||||
|
||||
let cam = api.mode.is_cam(),
|
||||
sla = api.mode.is_sla(),
|
||||
hi = cam ? api.var.layer_max - api.var.layer_lo : api.var.layer_hi,
|
||||
lo = cam ? api.var.layer_max - api.var.layer_hi : api.var.layer_lo;
|
||||
|
||||
updateSlider();
|
||||
STACKS.setRange(api.var.layer_lo, api.var.layer_hi);
|
||||
|
||||
|
|
@ -489,7 +484,7 @@ gapp.register("kiri.main", (root, exports) => {
|
|||
}
|
||||
|
||||
function loadImage(image, opt = {}) {
|
||||
const info = Object.assign({settings: settings.get(), png:image}, opt);
|
||||
const info = assign({settings: settings.get(), png:image}, opt);
|
||||
kiri.client.image2mesh(info, progress => {
|
||||
api.show.progress(progress, "converting");
|
||||
}, vertices => {
|
||||
|
|
@ -844,7 +839,6 @@ gapp.register("kiri.main", (root, exports) => {
|
|||
}
|
||||
|
||||
function setViewMode(mode) {
|
||||
const oldMode = viewMode;
|
||||
const isCAM = settings.mode() === 'CAM';
|
||||
viewMode = mode;
|
||||
platform.deselect();
|
||||
|
|
|
|||
|
|
@ -921,7 +921,7 @@ function fitDeviceToWidgets() {
|
|||
}
|
||||
|
||||
// extend API (api.platform)
|
||||
const platform = api.platform = {
|
||||
const platform = Object.assign(api.platform, {
|
||||
fit: fitDeviceToWidgets,
|
||||
add: platformAdd,
|
||||
changed: platformChanged,
|
||||
|
|
@ -950,6 +950,6 @@ const platform = api.platform = {
|
|||
show_volume: space.platform.showVolume,
|
||||
top_z() { return topZ },
|
||||
clear() { api.space.clear(); api.space.save(true) }
|
||||
};
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
// dep: kiri.api
|
||||
// dep: kiri.consts
|
||||
// dep: kiri.utils
|
||||
gapp.register("kiri.selection", [], (root, exports) => {
|
||||
gapp.register("kiri.selection", (root, exports) => {
|
||||
|
||||
const { kiri, moto, noop } = self;
|
||||
const { api, consts, utils } = kiri;
|
||||
|
|
@ -295,7 +295,7 @@ function setDisabled(bool) {
|
|||
}
|
||||
|
||||
// extend API (api.selection)
|
||||
const selection = api.selection = {
|
||||
const selection = Object.assign(api.selection, {
|
||||
move,
|
||||
merge,
|
||||
scale,
|
||||
|
|
@ -319,6 +319,6 @@ const selection = api.selection = {
|
|||
disable() { setDisabled(true) },
|
||||
opacity() { api.widgets.opacity(...arguments) },
|
||||
meshes() { return selectedMeshes.slice() },
|
||||
};
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
|||
|
|
@ -762,7 +762,7 @@ function setEnableWASM(bool) {
|
|||
}
|
||||
|
||||
// extend API (api.conf)
|
||||
api.conf = {
|
||||
Object.assign(api.conf, {
|
||||
dbo: () => { return ls2o('ws-settings') },
|
||||
get: getSettings,
|
||||
put: putSettings,
|
||||
|
|
@ -778,10 +778,10 @@ api.conf = {
|
|||
restore: restoreSettings,
|
||||
export: settingsExport,
|
||||
import: settingsImport,
|
||||
};
|
||||
});
|
||||
|
||||
// extend API (api.settings)
|
||||
api.settings = {
|
||||
Object.assign(api.settings, {
|
||||
get: getSettings,
|
||||
import: settingsImport,
|
||||
import_zip: settingsImportZip,
|
||||
|
|
@ -797,6 +797,6 @@ api.settings = {
|
|||
async put() {},
|
||||
status: false
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
// use: load.file
|
||||
// use: kiri.selection
|
||||
// use: kiri.platform
|
||||
gapp.register("kiri.widgets", [], (root, exports) => {
|
||||
gapp.register("kiri.widgets", (root, exports) => {
|
||||
|
||||
const { data, kiri, moto, noop } = root;
|
||||
const { api, consts, utils, newWidget, Widget } = kiri;
|
||||
|
|
@ -93,7 +93,7 @@ function opacity(value) {
|
|||
}
|
||||
|
||||
// extend API (api.widgets)
|
||||
const widgets = api.widgets = {
|
||||
const widgets = Object.assign(api.widgets, {
|
||||
load: Widget.loadFromCatalog,
|
||||
new: newWidget,
|
||||
map,
|
||||
|
|
@ -110,6 +110,6 @@ const widgets = api.widgets = {
|
|||
each(fn) { WIDGETS.slice().forEach(widget => fn(widget)) },
|
||||
for(fn) { widgets.each(fn) },
|
||||
forid(id) { return WIDGETS.filter(w => w.id === id)[0] }
|
||||
};
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue