How can I save images on Wix Database Collection with also other data witch is in the same module?(the images are optional to upload) I have tried several ways, but the only results that I achieved are:
When adding an image to the database it add the image on a new row
When trying to add the image within the "nuovoOrdine" object it doesn't work
.
import wixData from 'wix-data';
import wixLocation from 'wix-location';
import {addOrderInfoVideo} from 'backend/creazioneVideoAdClassico'
export function button4_click(event) {
if ($w('#input2').value != "") {
var image1url;
var image2url;
var nuovoOrdine;
var isFinished = false;
// This way it saves the image on the Database but on a new element.. it should add this image on the same element that have the data below ("nuovoOrdine")
// if ($w('#uploadButton4').value.length > 0) {
// $w('#uploadButton4').startUpload().then((uploadedFile)=>{
// image1url = uploadedFile.url
// nuovoOrdine = {
// 'fileNecessari1': image1url
// }
// isFinished = true
// addOrderInfoVideo(nuovoOrdine)
// })
// } else {
// if ($w('#uploadButton5').value.length > 0) {
// isFinished = false
// } else {
// isFinished = true
// }
// }
nuovoOrdine = {
// this should return the uploaded image link but it doesn't
'fileNecessari1': $w('#uploadButton5').startUpload().then((uploadedFile)=>{
return uploadedFile.url
}),
'puntiDiForza': $w('#textBox1').value,
'numeroOrdine': $w('#input2').value,
'colori': $w('#textBox2').value,
'idea': $w('#textBox3').value,
'link': $w('#input3').value,
'nomeProdotto': $w('#textBox3DAC315').value,
'concorrenza': $w('#textBox3DAC315DAC326').value,
'contatti': $w('#input1').value,
'dettagliExtra': $w('#textBox4').value,
'slider1': $w('#slider1').value,
'slider2': $w('#slider2').value,
'slider3': $w('#slider3').value,
'slider4': $w('#slider4').value,
'slider5': $w('#slider5').value,
'slider6': $w('#slider6').value,
'slider7': $w('#slider7').value,
'slider8': $w('#slider8').value,
'slider9': $w('#slider9').value,
'slider10': $w('#slider10').value,
'slider11': $w('#slider11').value,
'slider12': $w('#slider12').value,
'slider13': $w('#slider13').value
};
addOrderInfoVideo(nuovoOrdine)
// wixLocation.to('https://www.mywebsite.it/ringraziamenti-video-ads')
} else {
let textError = "Inserisci la mail con la quale hai effettuato l'ordine"
$w('#text133').text = textError
$w('#text133').text.bold()
}
}
Well, we can't really see your data operations, so it's a bit hard to tell, but I definitely see at least one thing you're doing wrong.
On this line over here, you're not waiting for your promise to resolve, so the property will not have the value you are looking for:
'fileNecessari1': $w('#uploadButton5').startUpload().then((uploadedFile)=>{
return uploadedFile.url
}),
Instead try something like this.
First add an async to you event handler function:
export async function button4_click(event) {
Then, do the image upload and wait for it to finish:
const uploadedFile = await $w('#uploadButton5').startUpload();
const uploadedUrl = uploadedFile.url;
Finally, create your object:
nuovoOrdine = {
'fileNecessari1': uploadedUrl,
'puntiDiForza': $w('#textBox1').value,
...
Related
I am trying to the create word detection on live camera feed using tensorflowJS in the web. (NOT NodeJS).
I have found a model which was shared on tfhub. I was trying to load that model in the web and trying to get some output. I somewhat finished the code to give some output to check before drawing on the canvas. I have tried so many versions of tfjs version to get the code working because some part of the code wasn't working when I was using a specific version, hence I did some reading documentation and copy pasting the code.
Finally, the code below is working but I dont understand the output and how do I use that output to draw anything on the screen? Am I missing any step?
Just for the reference I am also including the tfjs version that I am using in my code.
<script src="https://cdn.jsdelivr.net/npm/#tensorflow/tfjs-core"></script>
<script src="https://cdn.jsdelivr.net/npm/#tensorflow/tfjs-backend-cpu"></script>
<script src="https://cdn.jsdelivr.net/npm/#tensorflow/tfjs-tflite/dist/tf-tflite.min.js"></script>
Now the code for the detection ...
const videoElement = document.getElementById("webcam");
var model = undefined;
// Check if webcam access is supported.
function getUserMediaSupported() {
var state = !!(navigator.mediaDevices && navigator.mediaDevices.getUserMedia);
console.log(state)
return state
}
if (getUserMediaSupported()) {
enableCam()
} else {
console.warn("getUserMedia() is not supported by your browser");
}
// Enable the live webcam view and start classification.
function enableCam() {
// getUsermedia parameters to force video but not audio.
const constraints = {
video: true,
};
// Activate the webcam stream.
navigator.mediaDevices.getUserMedia(constraints).then(function (stream) {
videoElement.srcObject = stream;
});
}
videoElement.addEventListener('loadeddata', (e) => {
//Video should now be loaded but we can add a second check
if (videoElement.readyState >= 3) {
detect()
}
});
async function detect() {
$('.loading').text("loading...")
if (!model) {
model = await tflite.loadTFLiteModel("./ocr.tflite")
}
const outputTensor = tf.tidy(() => {
// Get pixels data from an image.
let img = tf.browser.fromPixels(videoElement)
img = tf.image.resizeBilinear(img,[320, 320]);
// Normalize (might also do resize here if necessary).
// const input = tf.sub(tf.div(tf.expandDims(img), 127.5), 1);
// Run the inference.
let inputTensor = tf.expandDims(img)
console.log("INPUT-->", inputTensor);
let outputTensor = model.predict(inputTensor);
console.log("OUTPUT-->", outputTensor)
// De-normalize the result.
return tf.mul(tf.add(outputTensor, 1), 127.5)
});
console.log(outputTensor);
// const input_tensor = await tf.browser.fromPixels(videoElement);
// // const input = tf.sub(tf.div(tf.expandDims(input_tensor), 127.5), 1);
// // const tensor = await tf.browser.fromPixels(imageElement)
// const input = tf.tidy(() => {
// return tf.reshape(input_tensor, [320, 320])
// .div(255).expandDims(0);
// });
// model.predict(input).then(predictions => {
// console.log('Predictions: ');
// console.log(predictions);
// });
// Run inference and get output tensors.
// let outputTensor = model.predict(input);
// console.log(outputTensor.dataSync());
// let input = tf.image.resizeBilinear(tf.browser.fromPixels(input_tensor), [320, 320]);
// input = tf.cast(tf.sub(tf.div(tf.expandDims(input), 127.5), 1), 'int32');
// // Run the inference and get the output tensors.
// let result = await model.predict(input);
// console.log(result)
// // renderDetectionResult(result);
// $('.loading').text("loaded")
}
Greets everyone,
Update: Solved it by a workaround, changing:
$numcflsinfpres = dbquery('SELECT fs_sub_id,fs_sub_cnt FROM '.$db_table['moveable_subs'].' WHERE fs_moveable_id='.$numcflinfparr['moveable_id']);
while($numcflsarr = mysqli_fetch_assoc($numcflsinfpres)) {
array_push($numcflinfparr['moveable_subs'],$numcflsarr);
}
to a function and used:
array_push($numcflinfparr[‘moveable_subs’], get_babylon_sub_object_data($numcflinfparr[‘moveable_id’]));
Old Text:
hope you can help me out with this:
I wanted to update JS object data by jquery (via $.ajax) by receiving PHP's mysqli_fetch_assoc array. It worked until I started using setInterval to update data every 15 minutes. Since then I get the following error: Uncaught (in promise) InternalError: too much recursion.
Also, tried only calling one object update (replacing for..of for a certain objectID), but I had no success. The error occurs on the line of $.ajax statement.
Edit: I could find that it occurs when an associative is pushed to array in this code:
function get_babylon_object_data($user,$id) {
$envobjects = array();
$envobjectsarr = mysqli_fetch_assoc(dbquery('SELECT object_id,object_user_id FROM '.$db_table['objects'].' WHERE object_id='.$id));
if(($envobjectsarr['object_id'] ?? 0)>0) {
$envobjectsarr['object_moveables'] = array();
if($envobjectsarr['object_user_id']==$user['id']) {
$numcflinfpres = dbquery('SELECT moveable_id,moveable_user_id,moveable_object_id,moveable_subobject_id FROM '.$db_table['moveable'].' WHERE moveable_object_id='.$envobjectsarr['object_id']);
while($numcflinfparr = mysqli_fetch_assoc($numcflinfpres)) {
$numcflinfparr['moveable_subs'] = array();
$numcflsinfpres = dbquery('SELECT fs_sub_id,fs_sub_cnt FROM '.$db_table['moveable_subs'].' WHERE fs_moveable_id='.$numcflinfparr['moveable_id']);
while($numcflsarr = mysqli_fetch_assoc($numcflsinfpres)) {
array_push($numcflinfparr['moveable_subs'],$numcflsarr);
}
array_push($envobjectsarr['object_moveables'],$numcflinfparr);
}
}
$envobjectsarr['object_subobjects'] = array();
$envsubobjectsres = dbquery('SELECT * FROM '.$db_table['subobjects'].' WHERE subobject_object_id='.$envobjectsarr['object_id']);
while($envsubobjectsarr=mysqli_fetch_assoc($envsubobjectsres)) {
$envsubobjectsarr['subobject_moveables'] = array();
if($envsubobjectsarr['subobject_user_id']==$client['id']) {
$numflinfpres = dbquery('SELECT moveable_id,moveable_user_id,moveable_object_id,moveable_subobject_id FROM '.$db_table['moveable'].' WHERE moveable_subobject_id='.$envsubobjectsarr['subobject_id']);
while($numflinfparr = mysqli_fetch_assoc($numflinfpres)) {
$numflinfparr['moveable_subs'] = array();
$numflsinfpres = dbquery('SELECT fs_sub_id,fs_sub_cnt FROM '.$db_table['moveable_subs'].' WHERE fs_moveable_id='.$numflinfparr['moveable_id']);
while($numflsinfparr = mysqli_fetch_assoc($numflsinfpres)) {
array_push($numflinfparr['moveable_subs'], $numflsinfparr);
}
array_push($envsubobjectsarr['subobject_moveables'], $numflinfparr);
}
}
$envobjectsarr['object_subobjects'][$envsubobjectsarr['subobject_object_pos']] = $envsubobjectsarr;
}
$envobjects[$id] = $envobjectsarr;
}
return $envobjects[$id] ?? array('object_id'=>$id);
}
Error: Uncaught (in promise) InternalError: too much recursion
aUpdateObject Updater.js:15
updateObject Updater.js:8
interval Updater.js:35
(Async: setTimeout handler)
interval Updater.js:32
(Async: setInterval handler)
initUpdater Updater.js:30
setup Central.js:29
onFinish Central.js:28
_decreaseWaitingTasksCount assetsManager.ts:1143
done assetsManager.ts:1176
_onDoneCallback assetsManager.ts:168
run assetsManager.ts:117
runTask assetsManager.ts:389
successHandler sceneLoader.ts:756
ImportMesh sceneLoader.ts:792
(Async: promise callback)
ImportMesh sceneLoader.ts:789
dataCallback sceneLoader.ts:552
GLTFFileLoader glTFFileLoader.ts:652
LoadFile fileTools.ts:343
onReadyStateChange fileTools.ts:457
(Async: EventListener.handleEvent)
addEventListener webRequest.ts:138
retryLoop fileTools.ts:482
requestFile fileTools.ts:485
RequestFile fileTools.ts:519
LoadFile fileTools.ts:342
_loadFile scene.ts:4416
_loadFile glTFFileLoader.ts:866
loadFile glTFFileLoader.ts:647
manifestChecked sceneLoader.ts:582
Database database.ts:69
OfflineProviderFactory database.ts:11
_LoadData sceneLoader.ts:603
ImportMesh sceneLoader.ts:765
runTask assetsManager.ts:379
run assetsManager.ts:114
_runTask assetsManager.ts:1194
load assetsManager.ts:1248
createScene Central.js:36
default Central.js:10
<anonym> index.js:5
InnerModuleEvaluation self-hosted:2325
evaluation self-hosted:2286
>jquery 128
isPlainObject
... (127x?) extend
File: Updater.js
export class Updater {
constructor(main) {
this.objects = {};
this.upobjects = {}; // update-requests-array
}
updateObject(id) {
if(!this.upobjects[id]) { // If no update-request ongoing
this.aUpdateObject(id);
this.upobjects[id] = id; // save update-request
}
}
async aUpdateObject(id) {
const aUpdater = this; // set to use in success function
$.ajax({
type: 'post',
url: 'path/to/updateData.php',
dataType:'json',
data: {user:aUpdater.data, id:id},
success : function (result) {
// Update Data, then Models and then UI
},
error: function(data) {
console.log('error');
console.log(data);
}
});
}
initUpdater() {
const updater = this;
this.interval = window.setInterval(function(){ // For every 15 minutes
let count = 1;
for(const object of Object.values(updater.objects)) { // For every object
setTimeout(function(){
updater.updateObject(object.id); // init single object update
},count*1000);
count++;
}
}, 900000);
}
}
File: Central.js
// Import BABYLON
// Import Updater.js
export default class {
constructor() {
this.canvas = document.getElementById('renderCanvas'); // Canvas
this.engine = new BABYLON.Engine(this.canvas, true, { stencil: true }); // prepare engine
this.scene = new BABYLON.Scene(this.engine); // init scene
this.createScene();
}
createScene() {
this.assetManager = new BABYLON.AssetsManager(this.scene); // Model Loader
this.updater = new Updater(this); // manage object updates
// this.updater.objects will be filled here and models loading is prepared
const central = this;
window.addEventListener('resize', function() {
central.engine.resize()
});
this.assetManager.onProgress = (remainingCount, totalCount, task) => {
console.log(remainingCount, totalCount, task.name);
}
this.assetManager.onFinish = (tasks) => { // If all 3d models are loaded
this.setup();
this.engine.runRenderLoop(function() {
central.scene.render(); // simulate scene
});
};
this.assetManager.load(); // Load 3d models
}
setup() {
this.updater.initUpdater();
}
}
File: index.js
// Import BABYLON
// Import Central.js
if (BABYLON.Engine.isSupported()) {
window.central = new Central(); // create Application
}
File: updateData.php
<?PHP
ini_set('MAX_EXECUTION_TIME', 1800);
define('CENTRAL_ROOT_DIR','..');
include_once(CENTRAL_ROOT_DIR.'/path/to/funcs.php'); // includes get_babylon_object_data()
include_once(CENTRAL_ROOT_DIR.'/path/to/config.php'); // includes DB config
dbconnect(); // connect to mysql DB
$conf = get_all_config(); // get app configuration
include_once(CENTRAL_ROOT_DIR.'/path/to/definitions.php'); // includes definitions
function get_babylon_object($user,$id) {
return json_encode(get_babylon_object_data($user,$id)); // get_babylon_object_data updates and returns $user (array) using mysqli_fetch_assoc to get DB data
}
echo get_babylon_object($_POST['user'] ?? array(),$_POST['id'] ?? 0);
dbclose(); // close DB
?>
I'm working on a web app that shows the total duration of a playlist. Here we're dealing with the YouTube API. And I want to know how should I get rid of the global variable newPageToken. Also I still need to use it in the third function on this snippet.
let newPageToken = null;
// Next page for more results (Max 50 per page)
function getNextTokenURL() {
console.log(newPageToken);
return newPageToken
? `${playlistItemsURL}&playlistId=${extractedPlaylistIDId}&pageToken=${newPageToken}&key=${API_KEY}`
: `${playlistItemsURL}&playlistId=${extractedPlaylistIDId}&key=${API_KEY}`;
}
async function getVideoIdsForPageToken() {
try {
const { data } = await axios.get(getNextTokenURL());
const nextPageToken = data.nextPageToken;
const videoIds = data.items.map((video) => {
return video.contentDetails.videoId;
});
return { videoIds, nextPageToken };
} catch (e) {
if (e.response) {
const { code, message } = e.response.data.error;
throw new Error(`StatusCode ${code}. Reason: ${message}`);
console.log("Errow while fetching videos list.");
} else {
throw new Error(e.message);
}
}
}
// Navigates between the videos per page and adds them (Maximum 50)
async function getPlaylistData() {
try {
const { videoIds, nextPageToken } = await getVideoIdsForPageToken();
let pageToken = nextPageToken;
newPageToken = pageToken;
const returnedVideoIds = [];
returnedVideoIds.push(getDetailsForVideoIds(videoIds));
const videoGroups = await Promise.all(returnedVideoIds);
for (const group of videoGroups) {
for (const video of group) {
finalTotalDuration += returnedToSeconds(video.contentDetails.duration);
}
}
// console.log(videoIds);
if (nextPageToken) {
await getPlaylistData();
}
} catch (e) {
throw new Error(e.message);
console.log("Error while navigating between video pages.");
}
}```
Assumptions
finalTotalDuration is also a global variable declared somewhere (Not a good idea)
You call getPlaylistData for multiple playlist for multiple users
Solution
You need to ensure the getPlaylistData is standalone and returns the finalTotalDuration as a return value (not set a global one)
To make it standalone it has to be iterative in nature. It should be a recursive function which does the following
async function getPlaylistTotalDuration(newPageToken) {
// Step 1: Create the required query URL based on the newPageToken parameter
// Step 2: Start a local duration counter
// Step 3: Get the video details based on the URL created in Step 1
// Step 4: Get the durations in seconds and add it to the local duration counter created in Step 2
// Step 5: Check if the return of Step 3 has a nextPageToken, if so do a recursive call to self with the new token
// Step 6: Return the final value, which will propogate back in a recursive function
}
You can simply call the function like
let finalTotalDuration = getPlaylistTotalDuration(null); // or getPlaylistTotalDuration();
for example the below getPlaylistTotalDuration is a replacement to your getPlaylistData method
async function getVideoIdsForPageToken(url) {
try {
const { data } = await axios.get(url);
const nextPageToken = data.nextPageToken;
const videoIds = data.items.map((video) => {
return video.contentDetails.videoId;
});
return { videoIds, nextPageToken };
} catch (e) {
if (e.response) {
const { code, message } = e.response.data.error;
throw new Error(`StatusCode ${code}. Reason: ${message}`);
console.log("Errow while fetching videos list.");
} else {
throw new Error(e.message);
}
}
}
async function getPlaylistTotalDuration(newPageToken) {
try {
// Step 1: Create the required query URL based on the newPageToken parameter
let url = newPageToken
? `${playlistItemsURL}&playlistId=${extractedPlaylistIDId}&pageToken=${newPageToken}&key=${API_KEY}`
: `${playlistItemsURL}&playlistId=${extractedPlaylistIDId}&key=${API_KEY}`;
// Step 2: Start a local duration counter
let totalDuration = 0;
// Step 3: Get the video details based on the URL created in Step 1
const { videoIds, nextPageToken } = await getVideoIdsForPageToken(url);
const returnedVideoIds = [];
returnedVideoIds.push(getDetailsForVideoIds(videoIds));
const videoGroups = await Promise.all(returnedVideoIds);
for (const group of videoGroups) {
for (const video of group) {
// Step 4: Get the durations in seconds and add it to the local duration counter created in Step 2
totalDuration += returnedToSeconds(video.contentDetails.duration);
}
}
// Step 5: Check if the return of Step 3 has a nextPageToken, if so do a recursive call to self with the new token
if (nextPageToken) {
totalDuration += await getPlaylistTotalDuration(nextPageToken);
}
// Step 6: Return the final value, which will propogate back in a recursive function
return totalDuration;
} catch (e) {
throw new Error(e.message);
console.log("Error while navigating between video pages.");
}
}
Note: I have not actually ran the above code, but hopefully you get an idea of what needs to be done.
On load, I'm receiving a list of image URL's that I want to hide from the users view.
I have an array of all the original image URL's as well.
I want to create a new array with out the hidden images URL's.
I am using the array.filter() function but It not removing the URL's from the array.
I think its the way I am loading the functions because hidden images is initially null, than it loads again and it has its values in there, but im not really sure what im not doing to get this to work properly.
Thanks for any insights.
useEffect(() => {
async function getImage(jobID) {
const imageURL = await Storage.list(`${jobID}/completed/`);
let imagesAsArray = [];
for (let i = 0; i < imagesToDownload.length; i++) {
const imagesDownloaded = await getURLFromS3(imagesToDownload[i]);
imagesAsArray.push(imagesDownloaded)
}
return imagesAsArray
}
async function onLoad() {
try {
const downloadedImage = await getImage(job);
if (hiddenImages !== null) {
hide(downloadedImage)
} else {
setImages(downloadedImage);
}
} catch (e) {
alert(e);
}
}
onLoad();
}, [job]);
function hide(imagesToFilter) {
const ImagesToView = (imagesToFilter).filter(image =>(!image.includes(hiddenImages)));
console.log(ImagesToView)
setImages(ImagesToView);
}
hiddenImages Value Example:
console.log(ImagesToView)
async onSubmit(formValue) {
this.isSubmitted = true;
if(this.selectedImageArray.length > 0) { // 4 images in this array
for (let index = 0; index < this.selectedImageArray.length; index++) { // Loop through this image array
await new Promise(resolve => {
setTimeout(()=> {
console.log('This is iteration ' + index);
var filePath = `images/tours/${this.selectedImageArray[index].name.split('.').slice(0,-1).join('.')}_${new Date(). getTime()}`;
const fileRef = this.storage.ref(filePath);
this.storage.upload(filePath, this.selectedImageArray[index]).snapshotChanges().pipe(
finalize(() => {
fileRef.getDownloadURL().subscribe((url) => {
formValue[`imageUrl${index+1}`] = url;
console.log(url);
});
})
).subscribe()
resolve();
}, 3000);
});
}
console.log('After loop execution');
// this.value(formValue);
}
}
After submitting the code it will download and print 3 urls and then it print 'after loop execution' then it print 4th one I don't understand why. See here in console
see in the image line no of code execution.
What I want to execute code in sequence after all images download then after it will go out of loop.
I wrote another version of this that hopefully works as you expect it to.
First we create an array of all the storage upload snapshot observables.
The we use concat() to run them all in sequence. (If you change from concat() to merge() they will all go at once)
The we use mergeMap to jump over to the getDownloadURL
Then in the subscribe we add the url to the formValues
Finally in the finalize we set the class propery "value" equal to the formValue.
onSubmit(formValue) {
const snapshotObservables = this.selectedImageArray.map(selectedImage => { // 4 images in this array
const filePath = `images/tours/${selectedImage.name.split('.').slice(0, -1).join('.')}_${new Date(). getTime()}`;
return combineLatest(this.storage.upload(filePath, selectedImage).snapshotChanges(), filePath);
});
concat(...snapshotObservables).pipe(
mergeMap(([snapshot, filePath]) => {
const fileRef = this.storage.ref(filePath);
return fileRef.getDownloadURL();
}),
finalize(() => {
this.value(formValue);
})
).subscribe(url => {
formValue[`imageUrl${index+1}`] = url;
});
}
I wrote a new function for multiple file upload
public multipleFileUpload(event, isEncodeNeeded?: Boolean):Array<any> {
if(!isEncodeNeeded){
isEncodeNeeded=false;
}
let fileList = [];
for (let index = 0; index < event.target.files.length; index++) {
let returnData = {};
let file: File = event.target.files[index];
let myReader: FileReader = new FileReader();
returnData['documentName'] = event.target.files[index]['name'];
returnData['documentType'] = event.target.files[index]['type'];
myReader.addEventListener("load", function (e) {
if (myReader.readyState == 2) {
returnData['document'] = isEncodeNeeded ? btoa(e.target['result']) : e.target['result'];
}
});
myReader.readAsBinaryString(file);
fileList.push(returnData);
}
return fileList;
}
In this function event is the event of the input and the isEncodeNeeded is conversion is needed. If this is true then it convert to base64 format.
The output format is
[{
"document": documentbyte,
"documentName": document name,
"documentType": file format
}]