Zapier - Dynamic Dropdown as an Action Field, using values from the source - zapier

While writing a Zapier app, I have encountered the following problem.
My app, let us call id AppX is an app you send data to.
When creating a Zap, the user chooses whatever trigger (source) he wants, let's say he chooses Mailchimp.
Then the user chooses AppX, chooses an Action which we will call "Notify AppX" and then he has 2 Action Fields to fill up.
Dynamic Dropdown that I generate on my side, meaning I return the json constructing this dropdown.
Dynamic Dropdown of all the possible data fields from the trigger he chose.
Basically in 1. he chooses where to send the data to on my app and in 2. he chooses which data to send. I have implemented 1. but fail to implement 2.
Now I have no way of telling, which app he chose as a trigger and which fields of data they provide but still I want them to be able to choose multiple variables from that source and send it to me.
This is very similar to what the Klipfolio app does so if you know it, I'm trying to replicate its pattern on the Zapier platform.
If I can even limit (minimum and maximum) the number of data fields he chooses to send my app that would be even better.
How can I implement this step 2?

Related

How do you save the Slack modal view ID for future updates?

I'm using Slack's modals + their new BlockKit interactive actions. I have a modal dialog with several section's that include select menu accessories. When one of those accessories changes (ex: user preference goes from Yes -> No), I want to update the modal's view to reflect the change in some contextual text.
The docs outline two ways to update a model. Because I'm not using the traditional modal inputs, I have to update the modal via the API and not via response_action. Proof: I don't even receive a view_submission payload at all... I receive a blockkit_action payload.
The docs conflict a bit. In the above link they say that to update a view you must pass in the returned ID of the view when it was opened:
Remember the view.id that was included in the success response when
you used views.open earlier? We hope you kept it, because you can now
use it to update that view.
But when you look at the docs for the views.open and views.update, it appears there is a second option: external_id. The views.update docs say this:
A unique identifier of the view set by the developer. Must be unique
for all views on a team. Max length of 255 characters. Either view_id
or external_id is required.
Initially I got everything working really nicely by choosing an external ID of myapp-mymodal-[userID]. But as soon as I tried opening the modal simultaneously on my Desktop + Mobile client, I started getting internal_error responses and have been unable to open the modal since!
So I started looking into saving the view ID, per the first quote. My problem is: that ID changes every time the modal opens. I don't understand how I am expected to possibly keep track of the 0-2 "active" view IDs that might be taking place across a user's Desktop + Mobile clients (or more than 2 if they have an iPad, a second laptop, etc).
I tried to look for some sort of unique client ID that I could either use to include in the external_id or in my view_id persistence logic, but given that Slack's API appears to be sesssion-less I couldn't find any such thing.
How do others solve this problem?
Try using the private_metadata field in the View
I initially did the same thing you did, which worked, but I wanted to avoid that edge case if possible. What I figured out, is that I could pass the external_id that I created when opening the view into the view's metadata, and then retrieve it when I receive an interaction.
When I set the external_id I set it to the userID + the current time (so it's always unique, even if the user opens the modal from different devices)
externalID := UserID + time.Now().String()
and pass that both as the external_id for the view, and as a string into the private_metadata.
PrivateMetadata string `json:"private_metadata"`
When the user interacts with one of my blocks and Slack sends me the interactive message, I retrieve the metadata like this:
Request.Payload.View.PrivateMetadata
I wrote my Slack app in Go, but I tried to make it clear for any language. Let me know if anything is unclear or needs expanding on - this is my first time giving back to the Stackoverflow community.

Concept for a grails app

I am working on a Grails project, its an accounting project. We have multiple clients and they can have multiple types of accounts. I have to create the 'create' page for client, there should be a way to add multiple types of account to the client.
So I was thinking of making a drop-down list with account types and few text boxes to enter account name and other info about account. Also, as a client can have multiple accounts, so I want to create a 'add' button, when clicked it would display a new row to add a new client. I have done this kind of UI before using javascript but in this case, as there is a drop-down list and other components, I think it would be very hard and may not work.
I was thinking of creating a partial view which would render each time user clicked the 'add' button with additional row, problem with this would be during validation errors, edit page and i would also have to pass all values each time user clicks 'add' button.
Is there any other for doing this?
For the template approach you must use ajax if you don't want to carry on the params that the user has already set.
It is possible to make new drop-down lists appear (or any group of elements inside a <div>) when a user clicks a button, since Grails already comes with jQuery you might want to take a look at the .clone() method.
The problem with the two listed approeaches is that it will be possible to have duplicates.
Now, another option is to use checkboxes, so you can check just the type of account you want.
But to be honest it does seems a bit odd or even inapropiate to let the user choose the type of account he wants with such freedom.

How would I organize the flow of this Rails code?

I'm using Shippinglogic to gather tracking information for submitted tracking numbers.
I'm handling a number of things behind the scenes of the UI, but I'm not sure how to properly organize this.
So here's the flow:
User submits tracking number either via form input or URL (example.com/track/1234567890). If the number doesn't already exist in the database, then the next step happens...
After a number is submitted, I run the number through some logic to determine who the carrier is (UPS, FedEx, USPS, DHL, etc). The user never specifies...it's all done automatically.
After the carrier is determined, then I need to make the actual call to the carrier API (via Shippinglogic) to get tracking information.
After I get the tracking details, I need to save it to the database.
Then, the tracking details are finally returned to the user.
Since users can submit either via form or via a URL (without any sort of POST action), I'm trying to run it all through my show method in the controller where I check if the number exists and if not, submit it via Number.create(:tracking_number => '1234567890') but once I get into the model, I just kinda get lost on what to do next.
Well I would have the users directed to the new or create actions where you can handle creation and detect if the record already exists. Once that's handled you most likely want to send them off to the show page where you can display the tracking information from your data source and any information you have saved in your database. This way you are preserving the nature of the application and other developers would be able to work with the application if they need to.
Edit:
I had a project like this and I move my detection code out into a separate function inside the model so I could make changes to it and abstract it from a specific call on the model. I performed my API requests in the background on the model so I could cache data in the database and refresh the records that were deemed active once an hour.
Basically if it needed to use the data from the record or save some data as part of the record I made a function in the model. This enabled me to split a bunch of functions out from specific modifications to controller actions and the like.

Session and Tabbed Browsing ASP.Net MVC

I'm once again looking into the world of tabbed browsing and Sessions. Looking over a few google searches it seems that there isn't a nice way of supporting this.
Does anyone know of a method that allows Bookmarking without stealing a session (cookieless) (and this doesn't work in MVC2 for dataannotations).
Supporting tabs in such a way that it's per use case (like Windows Workflow), going through two workflows at once.
I'm thinking a url in the query string might support this, but I'm wondering if anybody else has done a similar implementation.
[Edit] Use Case: Say I'm writing an application that uses something like Windows Workflow. Each UI workflow may do an action such as collect settings of a page and execute some external process. I may wish to do two of these workflows at once (not necessarily the same UI workflow). As such if I saved in session I would get:
a) Different tabs interfering with the workflow
b) Previous/Next buttons would be extremely difficult to work out, due to a).
I would like it so either, a user cannot open another tab to a url (don't think there is a 100% method of preventing this), or allow a user to use a UI workflow in isolation without one affecting another (much like running two workflows in two different browsers).
Hopefully that gives an indication of what I'm attempting to do.
Regards,
J
It sounds like you might be trying to do the following:
For example, let's say you have a two page questionaire, the first page has first name on it and the second page has last name on it. You desire that the user can open two tabs, and be at different pages in the questionaire while entering different data in the questionaire in each tab.
So in Tab A, you have entered Mark as the first name and submitted and you are at page two now in Tab A. You decide you are going to do a questionairre for your friend also, so you open up a new Tab, Tab B. In Tab B you enter Tom and submit the page.
Currently in the browser you have Tab A, which is at page 2 of the questionaire with firstname = "Mark" and Tab B which is at page 2 of the questionaire with first name = "Tom". Assuming you wanted to maintain both of these in session on the server here is an approach that i think will work for you.
When a web browser requests page 1 of your form, on a GET request(no posted questionaire data to the server), you supply a hidden field in the the response html and generate a random number to store in that field. When this form is submitted you do the following on the server:
Look in session using the random number as a key "var questionaire = session[Request.Form["questionaire_rnumber"]]
if the questionaire is not in session you create a new questionaire and update it's properties and stick it in session
var questionaire = new Questionaire();
questionaire.FirstName = Request.Form["firstName"]
session[Request.Form["questionaire_rnumber"]] = questionaire;
if the questionaire was in the session you simply update the object, and display the next page, however when you display the next page you will want to supply the hidden random number field in the html again, using the same random number you used on page 1.
This way you can hold any number of questionaires in a single session. With MVC.NET it should be straight forward for you to add the random number field to your view model and add the logic for looking in session for an existing questionaire or creating a new one and I think you'll be good to go.
You should keep in mind the possible issues with the approach also, like back button issues, security issues, and performance issues.
One example of a security and a performance issue would be that an attacker realizes your application works like this and the attacker requests page 1 of your form 10,000 times and submit the page 1 each time. You would have 10,000 questionaire objects in that one user session. If the attacker deleted his session ID cookie 10,000 times and for each session id cookie he created 10,000 requests for page 1 and submitted the page 1 form, you would have 100,000 questionaire objects cumulatively across 10,000 sessions on your server. So you should put some constraints on it also to protect your application, for example:
Any individual session can only have X questionaires in session
Any individual IP address can only have Y concurrent sessions (this you would probably need to track in the Application object)
ADDITIONAL RESPONSE TO ADDED USE CASE
Thanks for the use case. My solution should still work for you. You have two options.
If you want to ensure there is only one tab working with your workflow, then when the random number is passed to the server from a new tab you will be able to detect that there is another workflow in progress and that the random number from the new tab does not match the random number from the first, so you will throw an exception and show the user some messaging that says they can't start a new workflow until they finish the first one, and ask if they want to cancel the first. You have to ask if they want to cancel it because if they close their browser on the first workflow they started they will be stuck until their session expires. Which won't happen if they keep trying to start a new workflow.
Secondly, you could allow them to do multiple, but segment the context of each workflow by the random number, as suggested in the first answer. The whole point is that you are making little mini-sessions in your session, but keyed of a value that is only stored in the client. So since each tab has a different random number when the form posts to the server, it's easy to correlate that random number with an entry in your session that has all the information about the workflow initiated from that tab.
Hope this helps.
You need to store wizard state information in the client in some way, via query string or form values. As you've intuited, Session will not work. Nor will anything else that relies solely on what is on the server.

Assigning Fogbugz cases programmatically

I want to write an application that assigns Fogbugz cases programmatically, how would I accomplish this? Is it possible to achieve this given any of the following scenarios:
The user enters text in my
application's input field and the
Fogbugz report is opened in the
browser where the "note" field is
populated with the text from the user
input
The fogbugz report is assigned to the
specified user in the application
without the browser even being opened
i.e. the report is stored directly in
the DB.
I'm planning to add default values to the other fields as well so I would assume the process would be the same for adding text to the "note" field.
You can do this with the Fogbugz API. See the heading "Editing Cases" for the specifics on how to edit a case (which includes creating a new one). It's a little complicated (or perhaps just oddly designed) but, as I remember, you basically have to call cmd=new if you want to create a new case, supply your text in the 's' parameter and set the ixPersonAssignedTo to the correct person. For an existing case, use cmd=edit.
This is possible both with a regular form posted to your Fogbugz installation and some server side code that calls the API.
You might want to write a plugin for FB and allow others to use it. (share it or sell it)

Resources