Jump to content

LWSChad

Caspio Rockstar
  • Posts

    251
  • Joined

  • Last visited

  • Days Won

    33

Everything posted by LWSChad

  1. Thanks for the shout-out @kpcollier! This functionality is the default behavior for file inputs
  2. Indeed this, along with 'Read Data' for the data source did the trick. Caspio tech support was very helpful with this suggestion as well. Thank you
  3. I have been building Caspio applications for my own projects since 2014 and for clients since 2016. My best Caspio applications are DataPages embeded into iframes that are accessed from a parent dashboard and heavily augmented with custom JS and CSS files. They are delivered via AWS CloudFront, hosted by AWS S3, and SSL certified using AWS Certificate manager. Secure API token generation using AWS Lambda functions and AWS Gateway endpoints. Caspio Forum Leaderboard: https://forums.caspio.com/topmembers Some older comments: https://forums.caspio.com/topic/6900-any-programmers-for-hire/#comment-22007 Cheers
  4. Thanks for the reply. I did review these docs and perform the steps outlined in them and mentioned in your post. The issue I'm experiencing is that the external user is able to access the DataPages in my account when they follow the initial invite, however, they can't come back to it. I have tested this with my own external email addresses and experience the same issue. I'll reach out to support. Thanks again
  5. Hello, I am trying to let a 3rd party edit a specific DataPage. I have created a group with "Edit DataPage" permission for the single DP. The issue I am running into is that the user only was able to edit or access the DataPage on the 1st login. After that, they can't navigate to it, search for it using the app key, nor use a link to the dp edit page (https://acctID.caspio.com/ui/apps/app/datapages/dpName/appKey/folder/folderName). They are presented with the following error on any Caspio Bridge action. "Permission denied. Contact your internal administrator for more information." Does anybody know the process for allowing an external user to edit a specific DataPage? Thank You
  6. Great topic! I'll share my process and am would be eager to learn about some other ideas. Also, this approach may not work in all deployments - I use unique html files for every datapage, and use iframes on the main interface for multiple datapages per user interface page. Caspio DataPage folders: FolderName [5-14] // current dev folder for the current project, monthly update, weekly update, feature addition, patch, etc. FolderName [LIVE] FolderName [old-versions] DataPage updates : Revision history! This is a utilized tool when iterations are frequent and quickly live in CI/CD. (optional / not a step, an aid) Duplicate the datapage, append current date, and move it to the current dev folder. FolderName [LIVE]/datapage_newRecord_512, gets copied and renamed to FolderName[5-14]/datapage_newRecord_605 if duplicated on June 5th and during the work window / project / release of [5-14] A folder may have several different date stamped datapages. (dp_newRecord_605 - dp_editRecord_515) Each datapage change should pair with a file update. File structure: Git is an easy way to track and access version history for files and the file structure. It also greatly aids collaboration. GitHub is a great choice. GitLab is as well. Many good choices. (optional / not a step, an aid). Date versioned directories. /p/m-d (production directory dates reflect launch date) /d/m-d (development directory dates reflect start date) /old-versions/p[or]d/m-d File names do not change with the date. Directory names do change with the date. /d/5-14/dashboard.html >> /d/6-5/dashboard.html Development dir-names from project start date. Production dir-names from launch date. App Parameters: Use a parameter for the base URL and live version as the destination after login, and wherever you need. In Overview, find and click Manage in the App Parameters frame Update Cleanup. Live hosted file cleanup Remove the previous rollback directory from production. Leave stable launch being replaced in production as the new rollback. Remove all but the current dev directory. Local file cleanup Copy /p/5-2 and past /old-versions/p/5-2 Delete the previous rollback and keep stable launch as the new rollback. Move the previous dev directory to /old-versions/d/4-17 Caspio cleanup Move the previously live datapges from [LIVE] to [old-versions] Move the live datapges from [current-devFolder] to [LIVE] Delete the empty [currrent-devFolder] Dev > Test > Launch > Cleanup. For new projects / work windows / updates / etc. Copy all the files in the live version to a date-based dev directory (/d/5-14) Duplicate the datapage to update and copy or notate it's app key. Replace the app key in the html file the datapage belongs to with the one for the new datapage . Build and test locally (VSCode Live Server is a good choice). Push dev files to the /d/5-14 directory on the live server. (for online testing) Load application as normal. (log in) In the URL bar, replace the active directory. i.e. your.domain.com/p/5-2 with the dev directory your.domain.com/d/5-14. (load dev files) Test to approval Copy /d/5-14 to /p/6-5. (add the launch files to a new production dir) One last test. Update the app parameter to /p/6-5. (Launch) Wait a satisfactory period of time for live use to flush out any rollback level bugs , then perform a update cleanup. Keeps files backed up! Clearing cache isn't required at updates. EASY rollback if needed. (just update the app parameter Change the domain or subdomain easily across an entire account or set of DataPages using a given app parameter. I hope this help some people and others share their processes.
  7. Want to talk about a Caspio project? Schedule a meeting at https://lightbulb.as.me/new-project

  8. Hi @kpcollier, Choosing a specific value from a dropdown can be achieve with a bit of javascript. First, identify the dropdown element and create an array the represents the dropdown choices: const dropdownEle = document.querySelector('[name*=field_name]'); const dropdownChoices = dropdownEle.options; Next, create the makeSelection function: function makeSelection(selectionID) { // loop all the dropdown options for(let i = 0; i < dropdownChoices.length; i++) { // if the dropdownChoice matches the selectionID... if(dropdownChoices[i].value == selectionID) { // select the choice by the index number dropdownEle.selectedIndex = i; } } } Then, identify the cascading textfield and set it's onchange event to trigger the makeSelection function: const vEle = document.querySelector('[name=cbParamVirtual1]'); vEle.onchange = function() { makeSelection(vEle.value); }; I hope this helps
  9. To expand to all forms document.querySelector('[name*=Recordfield_name]').type = 'number'; Caspio names inputs according to the following syntax. Submission forms: <input type="text" name="InsertRecordfield_name" id="InsertRecordfield_name_includes_textstring_if_cascading" value="" class="cbFormTextField"> Edit and detail forms: <input type="text" name="EditRecordfield_name" id="EditRecordfield_name_includes_textstring_if_cascading" value="" class="cbFormTextField"> Virtual fields in all forms: <input type="text" name="cbParamVirtual2" id="cbParamVirtual2_includes_textstring_if_cascading" value="" class="cbFormTextField"> The code above for changing to a number field works because [name*=Recordfield_name] will target both InsertRecord and EditRecord inputs then change the type from "text" to "number"
  10. Hi @fundy, Temporary API tokens generated on login would be pretty cool indeed! One approach that successfully allows one to get an API access token while keeping API keys secure is to use an AWS Lamba function. Using a lambda means API keys are used in a server-side function, so the keys stay out of the browser, where they're vulnerable. Call this function with an endpoint exposed using an AWS API Gateway (for example). Successful requests respond with temporary access tokens (and errant calls return a descriptive error message). Lambda Function: var XMLHttpRequest = require('xmlhttprequest-ssl').XMLHttpRequest; // Node JS module module.exports.caspioApiAuth = (event, context, callback) => { const api_url = 'https://acctid.caspio.com/oauth/token'; const api_secret = '456'; // client_secret var api_id = event.queryStringParameters.api; // get client_id by passing it to the endpoint with a query string param: ?api=[client_id] getAccessToken(api_url, api_id, api_secret); function getAccessToken(url, cid, cs) { var authXhr = new XMLHttpRequest(); // declare an XHR object var api_token = ''; // declare a string varible for the token var body = 'grant_type=client_credentials&client_id=' + cid + '&client_secret=' + cs; // body string authXhr.open('POST', url); // set the XHR open attribute authXhr.send(body); // send the body // request made, response coming authXhr.onreadystatechange = function () { // on response, wait for the response to be ready if (authXhr.readyState === 4) // state 4 is the results if(authXhr.status === 200) { // 200 is success var response = JSON.parse(authXhr.responseText); // parse the response into an object api_token = response.access_token; // set the token respond(authXhr.status, api_token); // format and return the token response } else { // if it's not a success, explain why respond(authXhr.status, '! token error \n' + authXhr.status + ' \n' + authXhr.responseText.split('<title>')[1].split('</title>')[0]); } } // no else on readyStateChange because 4 is the only state that matters }; function respond(st, txt) { const response = { statusCode: st, // status codes tell the browser what to do with the response. headers: { 'Access-Control-Allow-Origin': '[approved origin or *]', }, // Required for CORS support to work body: txt, // the token or error message }; callback(null, response); // send a response } }; (this simplified version has not been tested, but was originally duplicated from a live Lamba)
  11. I just double checked https://acctid.caspio.com/rest/swagger#/Tables and total records returned in not included in API responses. Try running loops until a response with no results is returned. For example if you have 950 records... https://acctid.caspio.com/rest/v2/tables/tbl_customer/records?q.select=PK_ID&q.pageNumber=1&q.pageSize=1000 may return { "Result": [ { "PK_ID": 1 }, * 949 more results ] } then https://acctid.caspio.com/rest/v2/tables/tbl_customer/records?q.select=PK_ID&q.pageNumber=2&q.pageSize=1000 would return { "Result": [] } So when Result.length < 1, you've reached the end. I hope this helps
  12. I have bumped into long query string limits as well. This forum post provides some context: https://stackoverflow.com/questions/812925/what-is-the-maximum-possible-length-of-a-query-string Another approach would be to use fields to pass the data. Set the fields to text field or text area so you can pass the data on exit (fig.1). Then set the destination and messaging options to load the new page (fig.2). Lastly, capture the parameters in the submission DataPage with the ID field as a text field for editing (fig.3). fig.1 fig.2 fig.3 If that doesn't work, you can set up cascading fields to load data from the old ID. Set a virtual field to capture the old ID, use this as the parent field, set the lookup table to the table containing the original data, cascade on the old ID, and choose the appropriate field for the cascading value. I would try other options first as this will be a slloww DataPage if your data has many fields. I hope this helps
  13. Hi @kpcollier Then a bit of javascript to check for the parameter. <script> var p = '[@your_parameter]'; if(p !== '') { console.log('parameter present - auto search'); yourAutoSubmitFunction(); } else { console.log('no parameter - behave normally'); } </script> Pair this with the AutoSubmit described here (and that you mentioned) To prevent a loop, reset Caspio parameters with (cbResetParam=1 on the link back to search. Search form URL: /your-search-page.html?cbResetParam=1 I hope this helps
  14. Hi @CRamsey, I also think your first approach is the best solution. It looks like your authentication source is a view (PRM_User_Table_ preceding each option leads me to that conclusion). Check to make sure the Org_ID is in that view to have it show up there. If that doesn't do the trick, and the parameter approach is also not working (I am a bit confused why the Org_ID wouldn't be the same for all users the admin adds, but alas) you can get the Ord_ID with another approach. Set up a hidden virtual field to load PRM_User_Table_User_ID (from auth fields). Then set Org_ID as a cascading text field on the virtual field parent, User_Table as the lookup table, User_ID for filter cascade by, and Org_ID as field for value. I hope this helps
  15. Unsure, but I wonder if the authenticated DataPage has not had a chance to load yet so the test will always fail as it runs too early. Try an iframe deployment and run the check onload. <iframe name="dp_name" title="dp_name" src="https://123.caspio.com/dp/123">Sorry, but your browser does not support frames.</iframe> <script> var loggedInTestIfr = document.getElementsByName('dp_name')[0]; loggedInTestIfr.onload = function(){ checkLoggedIn(); }; function checkLoggedIn(){ var myTestElem = document.getElementById('loggedInTestDiv'); if (myTestElem == null) { //user not logged in console.log('Not logged in'); } else { //user logged in console.log('Logged in'); } } </script> What is the URL for you page? I'll take a look (if you also answer, or at least try to answer, the questions above)
  16. If you have updated your DataPages to use the subdomain for your account in the deploy code, the logout link now uses the account subdomain for your account. Rather than b5.caspio.com/folderlogout try ******.caspio.com/folderlogout where ****** is your Also, see: https://howto.caspio.com/deployment/caspio-site-vs-account-subdomain-deployment/ Hope this helps
  17. This behavior is displayed in many places my web-application. Create an account here Choose a free plan so you can log in to see this and other things Caspio
  18. Thanks Bruno, it was a pleasure working with you! I look forward to staying connected and seeing your project (great idea, I must say) grow and evolve!
  19. I do some Caspio and JavaScript freelance. I have thousands of hours of Caspio and JS experience, and can very likely build what you need. (basically full time since 2014) I am interested and able to help with small to medium sized projects. PM me for info. Some notable customers/projects include ezIQ.us QuoStudentTravel.com BaleDoneen.com Block-Trades.com MascotConstruction.com
  20. I want to see a list of available variables I can use here or there. What specifically brought me to this question were File Size error messages and a Date Format error messages that are vague and nondescript. I know I can change the wording, which helps, but I'd like to use the cool variables like "Are you sure you want to delete %n records" in the rest of my error messages. Does anybody know how to use these cool variables?
  21. Hello, I'm tying to improve my app's error messages using Localizations. I see on some error messages there are variables or parameters that provide the user with some very valuable information. Value cannot be shorter than %s characters. Value cannot be larger than %n characters. Are you sure you want to delete %n records. %p authorization failed. Cannot redirect to %p etc. Does anybody know how to use these, or where I can find a list of the variables we can use and how to? Thanks and ThinkEZ
  22. Thanks! Those are good options. I ended up using a workaround using ABSOLUTE. Substring([@field:ScratchPad], Charindex(': ',[@field:ScratchPad], Charindex('Passport Date of Issue: ',[@field:ScratchPad]) ) + 2, Abs( Charindex('===',[@field:ScratchPad], Charindex(': ',[@field:ScratchPad], Charindex('Passport Date of Issue: ',[@field:ScratchPad]) ) ) - Charindex(': ',[@field:ScratchPad], Charindex('Passport Date of Issue: ',[@field:ScratchPad]) ) - 2 ) )
  23. Hi, I'm stumped. This code works Substring([@field:ScratchPad],Charindex(': ',[@field:ScratchPad],Charindex('Departure Airport: ',[@field:ScratchPad])) + 2,Charindex(' ======',[@field:ScratchPad],Charindex(': ',[@field:ScratchPad],Charindex('Departure Airport: ',[@field:ScratchPad]))) - Charindex(': ',[@field:ScratchPad],Charindex('Departure Airport: ',[@field:ScratchPad])) + 2) This code breaks with only a minor adjustment: changing + to - at the very end Substring([@field:ScratchPad],Charindex(': ',[@field:ScratchPad],Charindex('Departure Airport: ',[@field:ScratchPad])) + 2,Charindex(' ======',[@field:ScratchPad],Charindex(': ',[@field:ScratchPad],Charindex('Departure Airport: ',[@field:ScratchPad]))) - Charindex(': ',[@field:ScratchPad],Charindex('Departure Airport: ',[@field:ScratchPad])) - 2) This code is a substring in example two that works until I add it to the code above Charindex(' ======',[@field:ScratchPad],Charindex(': ',[@field:ScratchPad],Charindex('Departure Airport: ',[@field:ScratchPad]))) - Charindex(': ',[@field:ScratchPad],Charindex('Departure Airport: ',[@field:ScratchPad])) - 2 Any help will be appreciated
×
×
  • Create New...