top of page

Forum Posts

Ahmad
Velo Master
Velo Master
Apr 26, 2023
In Velo Pro Discussion
Hello there, I have a website where members with a particular type of membership can create and delete users/members, the problem is, deleteMember has specific permissions that prevent this. When trying to do that, the method returns the following error: "applicationError": { "description": "Forbidden", "code": "FORBIDDEN", "data": {} } The method only works when called by an admin, and has no way to suppress the authentication or elevate it with wix-auth, the only workaround is to use the deprecated wixUsersBackend's APIs to delete the members. Edit: The updateMember method also has the same permissions issue, please provide some way to bypass these permissions. We're aware of the security concerns, but please, let us decide. I'd love to have a way to suppress the auth. of the method either by passing suppressions options or by elevating the permissions. @Yisrael (Wix) Ahmad~!
0
3
90
Ahmad
Velo Master
Velo Master
Nov 19, 2021
In Tips, Tutorials, Examples
Hello fellow developers and VeloPers 😉 Did you find yourself in a case where you want to validate an input field, but the validation needs to run on the backend, perhaps to check with 3rd party services? For example, checking if the entered IBAN is a valid one? Or if an email address exists in your external database? If your answer is YES, you should keep reading this example. 😁 In this example, you'll learn how to asynchronously validate an input field and only enable the form's submit button when the field's value is valid. Disclaimer: This is NOT a perfect solution, but more of a workaround that I personally use in my projects. In this example, we're going to check if an email exists in our database, and mark the email as invalid if it doesn't. To see a live example, open the demo website here. There are 4 steps to do it, click on the step to directly scroll to it. Basic Requirements. Writing the input field's validations. Triggering the validation on each input. Validating the email (Backend). Step #1: Basic Requirements Before we start our project, let's define our elements' selectors, and a cache variable to store some data. const $email = $w('#email'); const $submit = $w('#submitBtn'); // The form's submit button const $error = $w('#errorMsg'); // A text element to show errors const cache = { timer: { func: null, duration: 500 }, checking: false, email: { value: null, isValid: false }, valid_emails: [], onBeforeValidation: () => { // A function to run before the validation take place $submit.disable(); $error.collapse(); cache.checking = true; cache.email.value = null; cache.email.isValid = false; }, onAfterValidation: (result, email) => { // A function to run after the validation is done if (result.valid) { cache.email.isValid = true; cache.email.value = email; if (!cache.valid_emails.includes(email)) { cache.valid_emails.push(email); } } else { $error.text = $email.validationMessage; $error.expand(); } cache.checking = false; } } Step #2: Writing the input field's validations. The first thing we need to do is create our email validator, and pass it to the input's onCustomValidations() event handler. $email.onCustomValidation((email, reject) => { cache.onBeforeValidation(); if (typeof email === 'string') { if (!cache.valid_emails.includes(email)) { return new Promise((resolve, reject) => { if (cache.timer.func) { clearTimeout(cache.timer.func); cache.timer.func = null } cache.timer.func = setTimeout(() => { /* validateEmail is a backend function imported to this page, we'll create it in step #4. */ validateEmail(email).then(result => resolve(result)); }, cache.timer.duration); }).then((result) => { if (!result.valid) { reject(result.message) } cache.onAfterValidation(result, email); return; }) } else { cache.onAfterValidation({ valid: true }, email); } } else { reject('Please enter your email address.'); cache.onAfterValidation({ valid: false }); } }) Step #3: Triggering the validation on each input. Even though the validation is triggered on input, the validated value isn't the most recent one, it'll always validate the previous value of the input field, for example, when type in the first character in the input field, the value passed to the validation function from the event handler is an empty string, to overcome this issue, we need to rewrite the entered value each time an input is made to make sure the validation function uses the most recent value on the input field. $email.onInput(event => { const value = event.target.value; // Getting the latest value; event.target.value = value; // Overwriting the value; }) Step #4: Validating the email (Backend). To validate the email address (securely), we need to create/use a backend web module (.jsw). If you're not familiar with it please read this article from Wix. In our function, and for the simplicity of the example, we won't connect to a 3rd party service to validate the email, we'll just use a timeout to simulate the duration of a 3rd party service, and validate the emails against a local array in the module. export validateEmail(email) { if (!email) { return Promise.reject('Pleaes provide an email first.'); } // Array of predefined (valid) emails; const emails = ['contact@nasriya.net', 'support@nasriya.net']; return new Promise((resolve) => { setTimeout(() => { if (emails.includes(email)) { resolve({ valid: true }); } else { resolve({ valid: false }); } }, 1e3); }) } That's it for the example, happy to hear your feedback about it in the comments below. Notes: - Please don't comment asking for help to implement this on your website, if you need professional help you can either visit our support page or find a developer on the Marketplace. - If you find this helpful and you'd like to support us, please click here. Hope this helps!~ Happy Coding 💻 Ahmad - Nasriya Software.
3
2
365
Ahmad
Velo Master
Velo Master
Oct 09, 2021
In Tips, Tutorials, Examples
Recently, Wix has released a new collection/database for your site members, it contains their profile pictures, nicknames, and of course, their system IDs. The risks of exposing this data If your privacy policy promises your customers or members maximum security and privacy for their data, you should be concerned, this collection not only leaves you no choice to disable it, or change its permissions, but it also leaves you with a hole that you won't be able to fill in with your privacy policy, a potential hacker might be able to run malicious code on your website to get a list of all your members data, here's a brief of what the hacker will be able to get: The number of your members. The details themselves: Here's an example of the data that the hacker can, and will be able to get their hands on: [{ _id: "7VJsCV6Bj55waLJ9jYZV4EPXvdLawbUr", nuckname: "User 1", profilePicture: "https://static.wix.com/..........png" }, { _id: "tGYj26jTEz9BjNwnME4Z5MVdVZBRZn9x", nuckname: "User 2", profilePicture: "https://static.wix.com/..........jpg" }] I've made an argument for Wix, that in some websites and countries, the profile picture is considered confidential, and should never be publicly exposed unless the user explicitly allowed it, or has chosen to, remember guys, this is not a social network website, users don't provide their data to share it publicly, but rather to enhance their experience, unfortunately, Wix disagrees with me and just didn't listen, either way, whether they cared and listened or not, we're not just going to stand hand-in-hand, we must do something, fortunately, we've got your back. Block access to the collection To block access to the collection, we're going to use the collection's data hooks. We're going to use the following hooks: beforeGet. beforeQuery. beforeCount. Now on the backend, open the data.js file that was created upon creating the above hooks on the collection, and add the following code inside each one of the above functions. export function Members$PublicData_beforeGet(itemId, context) { return Promise.reject({ type: 'forbidden', message: 'Error: This action (get) is not allowed!' }) } export function Members$PublicData_beforeQuery(query, context) { return Promise.reject({ type: 'forbidden', message: 'Error: This action (query) is not allowed!' }) } export function Members$PublicData_beforeCount(query, context) { return Promise.reject({ type: 'forbidden', message: 'Error: This action (count) is not allowed!' }) } When someone - including you - tries to access this collection, they'll get an error message. Error: This action (query) is not allowed! Here's an example of what you - the admin - will get when you try to open the collection in the editor. You might be wondering: What if I want to get data from this collection? 🤔 The answer is simple, you only need to suppress the hooks, just like when you want to suppress the authentication of a user who doesn't have access to a resource, pass the suppression data as the options object to the method that you want to run, for example: wixData.get('Members/PublicData', "item_id", { suppressHooks: true }); // OR wixData.query('Members/PublicData').find({ suppressHooks: true }); You might also ask: What if I want to open the collection in the editor? Well, to do that, we first need to check the user authorization and only allow access to admins. Inside your hook function's code block, add the following code - do NOT redeclare the hook function. export async function Members$PublicData_beforeGet(itemId, context) { const isAdmin = async () => { if (wixUsersBackend.currentUser.loggedIn) { return wixUsersBackend.currentUser.getRoles().then((roles) => { return roles.filter(items => items.name === 'Admin').length > 0 ? true : false; }) } else { return false; } } const adminUser = await isAdmin(); if (!adminUser) { return Promise.reject({ type: 'forbidden', message: 'Error: This action (get) is not allowed!' }) } return itemId; } This way, only admins will have access to the resources, and the others' access will be blocked. Here you have it, folks, you've successfully patched that security hole and fulfilled your privacy policy. 😊 Hope this helps ~! 😉 See you next one 🖐 Ahmad
Block Access to The Public Data - Members/PublicData Collection! content media
3
7
483
Ahmad
Velo Master
Velo Master
Jul 25, 2021
In Tips, Tutorials, Examples
Hello Developers 🖐 Learn how to integrate your site with the Google SSO service and allow your site visitors to login/signup with their Google accounts. Watch the tutorial video and download its code files: https://www.nasriya.net/to/tutorial?id=xzz3etLbyqTt6AWz Read the written tutorial (Nasriya Developers Only): https://www.nasriya.net/post/tutorial-integrate-google-single-sign-on-sso-service-with-your-wix-website View live example: https://nasriya.net/login Tutorial Steps: Setting up the home page UI. Setting up Google Account Adding Nasriya's Google SSO Package. Add the code to the home page. Add the code to the routers.js file. Prepare the router page UI. Write the router page code. Edit the package configurations. Storing Google credentials in Wix Secrets manager. Testing the login Button. APIs we used: wix-router wix-users wix-users-backend wix-window wix-data Wants to see Facebook SSO next? Vote on this tutorial in the wishlist or request a new one. In the meantime, you can explore our youtube channel for other tutorials. Here you have it, folks, if you find it useful, please share it with your friends, or consider supporting us. Share your project with this integration with us so everyone can take a look at it 😊 Happy Coding. Ahmad
Tutorial: Google Single Sign-On Integration content media
6
0
1k
Ahmad
Velo Master
Velo Master
Jul 22, 2021
In Coding with Velo
Hello there 🖐 Yes, you read it right, we're working on this tutorial video right now! It's expected to go live the next Monday, the tutorial will be very easy even for beginners. I'll post the video here on the forum when it's done, and tweet it on our Twitter account, so follow us if you don't want to miss it. The tutorial will include: Setting up your Google Account. Edit the configuration. Write a frontend and a backend code. APIs we'll be using: wix-router wix-users wix-users-backend wix-window wix-data wix-captcha-backend In the meantime, you can explore our youtube channel for other tutorials. If you wonder how you can support us, a few nice words are enough, so smash that ❤️ button and let the party begin. Ahmad
1
0
50
Ahmad
Velo Master
Velo Master
Jul 16, 2021
In Velo Pro Discussion
Hey there, Short question, I tried the following regexp in different places before deciding to use it in the Editor's IDE, and it works flawlessly, but the IDE is giving a warning, does it need to be declared differently? BTW, this regexp is to validate email addresses. /^(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])$/ const regex = /^(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])$/ regex.test('contact@nasriya.net'); The warning is "Unexpected control character(s) in regular expression". Edit: The actual problem is that using this regex makes everything after it a string. Any ideas?
1
21
747
Ahmad
Velo Master
Velo Master
Jul 05, 2021
In Coding with Velo
You don't need a form to save your data to a database, you can just click on something to edit it right away, the values will be saved immediately without a submit button. Watch this video to learn more. Vote on this request to make this tutorial happen. Please let me know if you have any feedback in the comment section below. Ahmad
Video: Instantly Edit Database Values Without a Form content media
2
11
140
Ahmad
Velo Master
Velo Master
Jun 12, 2021
In Velo Pro Discussion
Hello Wix Team 🖐 I've noticed a weird behavior when using the scroll to the method, especially when assigning the scrollTo method to another method, for example: const element = $w('#element'); const scrollTo = $w('#element').scrollTo; element.scrollTo(); // It works scrollTo(); // Returns an error The returned error: Cannot read property 'getComp' of undefined Any idea? Ahmad
1
8
128
Ahmad
Velo Master
Velo Master
May 03, 2021
In Tips, Tutorials, Examples
Hey, there fellow developers ... In this example, I'll demonstrate how to create a simple messaging app to engage users on your website, this is important for support websites, eCommerce stores, social media websites, and many more scenarios. We'll be using the real-time APIs to publish messages. On the backend, store the message in a database for future reference then publish the message to the user's channel. Example: // Theoratical users const john = { name: 'John', id: 'random-text-1' } const ahmad = { name: 'Ahmad', id: 'random-text-2' } Now to communicate with each other, ideally, when John visits my profile, you need to check MY settings if I accept non-friends messages and that John isn't blocked by me. (not included in the example, let me know if you're interested to know how). Then, once John clicks "Message Ahmad", a chat window will be opened based on my ID, and you'll need to subscribe John to my messages' channel as well as his. Prepare the environment import wixRealtime from 'wix-realtime'; const messages = []; // Storing the conversation messages locally. 1. Add a messages listener. In this step, we'll handle the messages sent by me "Ahmad" to John. // Subscribe to my channel const ahmadChannel = { name: 'user-messages', resourceId: `msg-${ahmad.id}` } wixRealtime.subscribe(ahmadChannel, (notification, channel) => { /* All received messages from "Ahmad" are meant for John, we can control that later on */ const message = { _id: notification.payload.id, // a unique message identifier origin: 'forign', // Determain who own the message. date: new Date(), // The date that the message was received on. message: notification.payload.message // The actual mesage } // Add the message to the messages array messages.push(message); // Update the repeater displayed messages: $w('#repeaterMsgs').data = messages; }) 2. Allow John to receive his messages on other devices. Most of the time, you'll have more than one device opened, say for example on your computer and your phone, this will ensure that whatever John sends me from his computer will also appear on the conversation on his phone. /* Subscribe to John messages. This is important because we want other tabs/pages that the website is opened on to listen to the messages and display them as well, so when John sends a message to me from his laptop, the message will also appear on his phone or computer. */ const myChannel = { name: 'user-messages', resourceId: `msg-${john.id}` } wixRealtime.subscribe(myChannel, (notification, channel) => { /* All received messages from the user himself, but we need to check whether the message is sent from this device/tab/window or not */ if (messages.map(items => items._id).indexOf(notification.payload.id) === -1) { // Store the message and display it const message = { _id: notification.payload.id, // a unique message identifier origin: 'me', // Determain who own the message. date: new Date(), // The date that the message was received on. message: notification.payload.message // The actual mesage } // Add the message to the messages array messages.push(message); // Update the repeater displayed messages: $w('#repeaterMsgs').data = messages; } else { // Ignore the message because it's already here. } }) 3. Allow John to send messages (Backend & Frontend). To allow John to send me a message, we need a backend module and a frontend app. A) Prepare the backend function that will publish the messages: import wixRealtimeBackend from 'wix-realtime-backend'; export function sendMessage(message, toId) { // Specify the user channel const channel = { name : 'user-messages', resourceId: `msg-${toId}`}; // Prepare the payload const payload = { id: String(Math.floor(Math.random() * 10000)), message: message } // Prepare the payload options const payloadOptions = { users: [toId], includePublisher: true } */ users: List of users to receive the message, in our case only one person should receive it, which is the specified person */ // Publish the message to the specified recipants return wixRealtimeBackend.publish(channel, payload, payloadOptions) .then(() => { // You can store the message in a database here return Promise.resolve(); }); } In this step, you can store the messages in a database to view them on tabs opened later, see when it's delivered, seen, and more. (Not included in the example). B) Now prepare the frontend app to send the message, we'll create a function that will be triggered when the user clicks on "Send" or hit "Enter". // Import our backend function, make sure to replace the module below with your module name import chat from 'backend/myModule.jsw'; function send(message) { // Check if there's something to send or not. if (typeof message === 'string' && message.length > 0) { // Add the message to the messages array messages.push(message); // Update the repeater displayed messages: $w('#repeaterMsgs').data = messages; // Send the message return chat.sendMessage(message).then(() => { // Handle the case where the message is successfully sent }).catch(err => { console.error(err); // Mark the failed message as "not sent" with red marker or something. }) } } $w('messageInputBox').onInput(event => { // Enable the "Send" button if there's a message and disable it if otherwise if (event.target.value) { if (!$w('sendBtn').enabled) { $w('sendBtn').enable() } } else { if ($w('sendBtn').enabled) { $w('sendBtn').disable() } } }) // Trigger the the function to send the message. $w('sendBtn').onClick(() => send($w('messageInputBox').value)); $w('messageInputBox').onKeyPress((event) => { if (event.key === 'Enter') { // Check if the user wants to send the message or create a new line if (event.shiftKey) { // Create a new line $w('messageInputBox').value = `${$w('messageInputBox').value}\n`; } else { // Disable the text input $w('messageInputBox').disable().then(() => send($w('messageInputBox').value)); } } }) Here you have it, folks, if you have any questions feel free to ask in the comments below, if you want to request a tutorial about this topic you can do that too. Take a look at my previous tutorials videos. Hope this was helpful~! Ahmad
6
8
1k
Ahmad
Velo Master
Velo Master
Apr 04, 2021
In Velo Pro Discussion
Hey there 🖐 After initializing timelines for multiple elements inside a multi-state box, and getting to another state, and then get back to the same state, I get these lines logged to the console. Timeline play: Timeline not initiated Timeline play reverse: Timeline not initiated Here's the code that initializes the animation when the page is ready. parent.childeren.forEach(id=> { const item = $w(`#element${id}`); const timeline = wixAnimations.timeline(); timeline.add(item, { duration: 150, y: -5 }); item.onMouseIn(() => timeline.play()); item.onMouseOut(() => timeline.reverse()); }) I only get the message when I change the state of the box again, where the animation doesn't work, and print these messages to the console. I remember a thread from the past where dropdown menus or other components - I don't really remember exactly - couldn't keep their values when the state is changed, it might be something similar 🤷‍♂️ Anyone from Wix front-end devs can take a look at it, there's another issue regarding the styling of the components. Thanks in advance. Ahmad
0
8
152
Ahmad
Velo Master
Velo Master
Mar 27, 2021
In Velo Pro Discussion
Hey there, Recently one of my repeaters refused to display any data I pass to it, even a blank item ({_id: 'randomText'}), I can see the items by reading the repeater's data, but nothing is displayed in the UI as if it has no items at all! Here's the code where the repeater is populated: $w('#savedAddresses').data = []; const addresses = []; settings.address.list.forEach(address => { let item = { _id: `address-${Math.floor(Math.random() *100000)}`, address: address, isDefault: false } if (item.address.formatted === settings.address.main.formatted) { item.isDefault = true } addresses.push(item); }); addresses.sort((a, b) => { if (a.isDefault) { return -1 } else { return 0 } }) console.log("Addresses before assigning:", addresses); // Printing an array of 1 item $w('#savedAddresses').data = addresses; console.log("Addresses after assigning:", $w('#savedAddresses').data); // Printing an array of 1 item And here's the printed item: { "_id": "address-12473", "address": { "formatted": "address", "location": { "latitude": number, "longitude": number }, "city": "city" }, "isDefault": false } Any idea? Help is appreciated! Ahmad
0
2
56
Ahmad
Velo Master
Velo Master
Feb 04, 2021
In Velo Pro Discussion
Hey there .. The replaceAll( ) JS method is working as expected on frontend (Chrome browser), but it's not running on the backend, I get an error variable.replaceAll() is not a function. I've checked the compatibility of the method on Node.js. const text = 'A paragraph here'; const removeSpaces = text.replaceAll(' ', ''); console.log(removeSpaces); /* Result: Backend: text.replaceAll is not a function. Frontend: "Aparagraphhere" */ As a workaround, I used the regular replace( ) JS method. // Backend: let text = 'A paragraph here'; While (text.includes(' ')) { text = text.replace(' ') } Any idea why? And what can I use instead? Thanks in advance.
0
7
103
Ahmad
Velo Master
Velo Master
Jan 22, 2021
In Tips, Tutorials, Examples
Hey everyone 🖐 A new tutorial video (and code) demonstrating how to automatically detect the geolocation of the visitors on your site, their IP addresses, countries, cities and more, we'll also show you how to use REST APIs to connect to 3rd party services and use a dropdown menu with all the countries in the world, their flags and dialing codes. You can use this example in your Wix site in forms where you need the location of the visitor, phone numbers and more, for example, on sign up pages, or on carts where you want to preshow the shipping costs based, or show content related to visitors locations. Preview the example: https://nasriyasoftware.wixsite.com/example348647/detect View this tutorial video, materials and code: https://www.nasriya.net/to/tutorial?id=PHaKx7yUGyBdvR22 View our list of tutorials and examples: https://www.nasriya.net/to/link?id=zk43MGUGjJPMrb3e View or vote on existing tutorial videos on the Wishlist: https://www.nasriya.net/to/link?id=v4BN2RKmpBDdZCWk Request a new tutorial here: https://www.nasriya.net/to/link?id=vy7wGqUc8YMe2Gps Hope you find the video useful, if you did, please like the video and share it with the community. Ahmad
Tutorial: Detect Visitors' Geolocation & IP Address content media
1
4
3k
Ahmad
Velo Master
Velo Master
Jan 03, 2021
In Tips, Tutorials, Examples
Demonstrating how to create a smooth full screen scrolling animation with one single scroll on Wix sites. This tutorial is for beginners, but require full attention to the details in order to understand. Preview the live example: https://nasriyasoftware.wixsite.com/example65465 View the tutorial video and its code here: https://www.nasriya.net/to/tutorial?id=W79B3uN9rgrefC55 APIs used: onViewportEnter( ), onViewportLeave( ).
1
6
919
Ahmad
Velo Master
Velo Master
Dec 23, 2020
In Tips, Tutorials, Examples
Demonstrating how to display Wix Stores products catalog with a search bar, dropdown filters and sort the results with a drop down. The tutorial includes filtering the products with a dataset, and with data binding. with wix-data and backend modules. View the tutorial video and its code here: https://www.nasriya.net/to/tutorial?id=LtqxU28upJtrzP2x APIs used: wix-data
3
0
369
Ahmad
Velo Master
Velo Master
Dec 21, 2020
In Tips, Tutorials, Examples
Hi Velo Developers 🖐 We're pleased to announce a new Wishlist where you can view tutorials requested by others, and vote on them, or request a new one by yourself. You can also take a look at tutorials and examples we already made, or are making at the moment. Subscribe to our mailing list to get notified once a new tutorial is live, or subscribe to our YouTube channel. Please comply to our Community Guidelines and the Velo forum Community Guidelines. Please let us know what do you think, how we can improve, and if you have other ideas, your feedback is greatly appreciated 😉 Ahmad
7
13
1k
Ahmad
Velo Master
Velo Master
Dec 09, 2020
In Velo Pro Discussion
Hi there 🖐 The previous method demonstrated by Ed (Wix) on this post is no longer working. let imageUrl =`https://static.wixstatic.com/media/${fileName}`; This URL is now returning a Forbidden message. Any ideas? Help is appreciated.
0
4
162
Ahmad
Velo Master
Velo Master
Oct 11, 2020
In Velo Pro Discussion
Hi there 🖐 The sendMessage() function is not working for me, I'm getting the channel ID of the client, sending it to the backend to send a personalized message to the chatbox of the client on the frontend. // Frontend import {sendChannelId} from 'backend/chat.jsw'; $w.onReady(async () => { // Get the channel ID of the client. let channelId = await $w('#wixChat').getChannel({ type: 'Focused' }); // Send the channel ID to the backend. sendChannelId(channelId); }) // Backend - chat.jsw module import wixChatBackend from 'wix-chat-backend'; export function sendChannelId(channelId) { if (typeof channelId === 'string') { return wixChatBackend.sendMessage({ messageText: 'Test Message', channelId: channelId }).then(() => { return { type: 'success' } }).catch(err => { return { type: 'error', message: String(err) } }) } else { return { type: 'error', message: `The channel ID type ${typeof channelId} is invalid.` } } } It doesn't seem to be working 😕 Help is appreciated.
0
4
137
Ahmad
Velo Master
Velo Master
Oct 02, 2020
In Velo Pro Discussion
Hi there 🖐 I was trying with this for hours now, and can't figure out why I'm receiving this error! Here's the code: export function getCalculatedRelatedItems(discountedPrice, name, itemsToGet) { let maxPrice = (Number(discountedPrice) * 20 / 100) + Number(discountedPrice); let minPrice = Number(discountedPrice) - (Number(discountedPrice) * 20 / 100); return wixData.query('Stores/Products').contains('name', name).le('discountedPrice', maxPrice).and(wixData.query('Stores/Products').contains('name', name).ge('discountedPrice', minPrice)).limit(itemsToGet).find({suppressAuth: true}).then((result) => { if (result.length > 0) { return result.items; } else { return []; } }).catch(err => { console.error(err); return []; }) } The error that I'm getting from the catch method: Object = { name: "Error", errorGroup: "User", code: "WD_VALIDATION_ERROR" } Here's the error that I get when I remove the catch method: Object = { message: "Unknown token discountedPrice -> Map($lte -> 600)", details: {} // Empty Object } Any ideas what's the reason behind this? Any help is really appreciated! Thanks in advance. Ahmad
0
2
148
Ahmad
Velo Master
Velo Master
Sep 09, 2020
In Velo Pro Discussion
Hello there 🖐 One big problem I've had for a long time, when running one of the above functions on an array (regular and repeater data) sometimes I need to wait until a promise is resolved before continue to the next item, use case is if the array holds IDs that you need to query, or an upload button that's awaiting the URL of the uploaded item, it's just insane, this where I always stuck in each project and can't find any workarounds, the code is just ignoring the async/await as if it wasn't there. Any workarounds guys? Any suggestions? Thanks in advance.
0
17
136

Ahmad

Forum Moderator
Velo Master
Velo Certified
Content Creator
+4
More actions
bottom of page