Generating an email list from AppMaker Database - google-app-maker

I am trying to figure out how I can get database information involving the email column, make an array with all of the emails and then use the "button" feature to populate the "To:" part of an email page.
Any help is appreciated. Very new at this and pointing me on where to get the info would be great. Thanks

I recommend you to run a server script that would query the datasource that has the emails. The script will look something like this:
function getEmails(){
var query = app.models.<yourmodel>.newQuery();
var results = query.run();
var allEmails = [];
if(results.length > 0){
for(var i = 0; i < results.length; i++){
var uniqueEmail = results[i].<emailfieldname>;
allEmails.push(uniqueEmail);
}
}
return allEmails.join();
}
Then add a script to the button widget "onclick" event that will run the server script and manipulate the returned data. Something similar to this:
function poulateToField(response){
<widget path>.text/value = response;
}
google.script.run.withSuccessHandler(poulateToField).getEmails();
The above widget path would be the path to the "To:" widget, which can be a text box, text area, etc. In my case, I used a text area and the path was this "widget.parent.descendants.TextArea1.value"
I hope this helps. If you have more questions, just let me know! :)
P.D. Please don't forget to review the official documentation for a better and more detailed explanation.

you can also use projections to get a list of items (emails) from your datasource. As per this Article https://developers.google.com/appmaker/ui/binding#projections:
Projections let you access properties from records in a datasource's
items list. Access projections with the ..projections.. option in the
advanced binding wizard, or use the projection operator .. in a
binding path. For example, for an Employees datasource with a name
property, #datasources.Employee.items..name returns a list of all
employees' names.
You can check the "Call Scripts" guide which shows you how to send emails using App Maker which is available here https://developers.google.com/appmaker/tutorials/call-scripts/
To use projections and following the above guide, in Step #2 under "Create the UI": Add a text box for the recipient:
c. In the Property Editor, instead of entering the "To" value to the Textbox widget, you can select Binding and bind the widget to the Datasource projections following this path: datasource > items > ..projections.. > Email (name of the datasource field where the emails are located)
For example a projection will look like this: #datasource.items..email
This will automatically bind all emails that are available in your datasource to the text box widget. Then you can complete the guide and emails will be sent to all the email addresses in your datasource. Hope this helps.

Related

Display Text for QnAMaker follow-on prompts

I'm attempting to use follow-on prompts within QnAMaker but am confused about the purpose of the field labelled "Display text" in the "Follow-up prompt" creation dialogue. https://learn.microsoft.com/en-us/azure/cognitive-services/qnamaker/how-to/multiturn-conversation describes this field as "The custom text to display in the follow-up prompt.". To me, that suggests that it's just a label for the follow-up prompt which is typically rendered as a button. I therefore assumed that the text had no purpose other than as a label and that the button would be directly linked to the chosen question / answer pair. However, from experimenting with a QnAMaker knowledge base, it seems that the "Display text" is actually passed to the QnAMaker service and this text is used to search for the answer. This means that the "Display text" value has to be chosen for the purpose of both labelling the button and successfully finding the follow-on answer.
This means I can't use short follow-on prompts such as "How do I pay for it?" or "How do I join it?" where the main Q/A pair relates to one of various services as these strings won't reliably return the intended answer. Rather, the prompts will have to be the more verbose "How do I pay for service A" and "How do I join service A".
Have I understood this correctly? I don't think the documentation makes this at all clear...
Multi-turn QnA Maker conversations are still in preview and there is currently no SDK to help you build a bot that knows how to interact with the follow-up prompt API. You are ultimately in control, and so you get to have your bot treat the display text however it wants. All the "display text" is is a value that you've inserted into an answer in your knowledge base so that it gets returned along with the answer after a call to generateAnswer.
It can be very helpful to have your display text match the text of the question you're linking to because then the prompt's display text can be used to access the correct follow-up QnA pair, so long as the context is included in the API call. That's what happens in this sample. It sounds like you want to get it to work without having the prompt's display text match the text of the follow-up question. That can get tricky, but here's something you can do.
Remember that you specify more than just display text when you make follow-up prompts. You also link to a specific QnA pair. This allows the API to return that QnA ID to you along with the display text. You haven't mentioned which channel your bot is targeting, but if you're using a channel that supports postBack or messageBack actions then you can pass the QnA ID to your bot invisibly and then your bot can use that to access the answer. If you go this route, you may not even need to worry about dialogs or state. You also haven't mentioned what language you're coding your bot in, but here's an example of how this might be implemented in Node.js:
async testQnAMaker(turnContext) {
var qna = new QnAMaker({
knowledgeBaseId: '<GUID>',
endpointKey: '<GUID>',
host: 'https://<APPNAME>.azurewebsites.net/qnamaker'
});
var value = turnContext.activity.value;
var qnaId = value && value.qnaId;
// qnaId will be undefined if value is empty
var results = await qna.getAnswers(turnContext, { qnaId });
var firstResult = results[0];
if (firstResult) {
var answer = firstResult.answer;
var resultContext = firstResult.context;
var prompts = resultContext && resultContext.prompts;
if (prompts && prompts.length) {
var card = CardFactory.heroCard(
answer,
[],
prompts.map(prompt => ({
type: 'messageBack',
title: prompt.displayText,
displayText: prompt.displayText,
text: prompt.displayText,
value: { qnaId: prompt.qnaId }
}))
);
answer = MessageFactory.attachment(card);
}
await turnContext.sendActivity(answer);
} else {
await turnContext.sendActivity("I can't answer that");
}
}
Note that this does have some limitations. Because it works by retreiving the QnA ID from the activity's value property, it may not be able to find the correct QnA pair if the user types in the text of the button manually instead of clicking the button.
If you want to make the display text work on its own without relying on the QnA ID, you could save your own mappings so that your bot knows which display text values correspond to each QnA ID in each context. However, you might also consider just adding the display text as an alternative phrasing of the question in the QnA pair. So "How do I pay for service A" and "How do I pay for service B" could both have "How do I pay for it" as a form of the question. Because you'll now have duplicated phrasings in multiple QnA pairs, you'll need to pass the context in your calls to generateAnswer for this to work.
See this answer for more info about multi-turn conversations.

Cannot add new correlated record to new created record

When I create new record in Google AppMaker and then try to add correlated record to this new one I get this warning in console:
com.google.apps.appmaker.client.datasource.AbstractModelDataSource
WARNING: Could not find element with key RecordKey{key=private$7,
model key=...
Both datasources are set to:
Manual save mode
Automatically load data
The problem doesn't appear when I refresh the page or try to add correlated record to other existing record.
Anybody knows what could be a reason for this error?
App Maker doesn't allow to have unsaved changes on both ends of relation, most likely it is a reason, why you recieve error message in the first case. But in theory it should work once you save one of the relation ends (first save one of the records and then link them and save again):
var countryDs = app.datasources.Country;
var capitalDs = app.datasources.Capital;
countryDs.createItem();
countryDs.item.Name = 'United States';
countryDs.saveChanges(function() {
capitalDs.createItem();
capitalDs.item.Name = 'Washington, D.C.';
capitalDs.item.Country = countryDs.item;
capitalDs.saveChanges();
});
OK, I fixed it.
I have two forms. First to create item. Second to edit data. In the first form page need to be set to:
On Detach: Clear Changes To Datasource.
Datasources need to be set to autosave.

Adding a Dynamic Child to my Firebase Reference URL

I've been attempting to dynamically add a child to my firebase data reference URL, so far with no luck.
Assume I have the following data structure:
MyApp
|-beta_signups
|-users
|--fred
|----email "fred#test.com"
I would like to be able to add people who sign up, as a child based on their email address under the "signups" section. here is what I tried, but it didn't work.
var myDataRef = new Firebase("https://myapp.firebaseio.com/beta_signups/");
$('#submit').click(function() {
var email = $('#email').val();
myDataRef.child(email).push({email: email, beta_key: false});
$('#email').val('We got it.');
});
Any suggestions on how I can dynamically add the child?
You can't use an email address as the key for a child path because it contains invalid characters. See Creating References in the docs.
You are also creating a child based on the email address, and then creating a child of the email by using push. Probably, you should just get rid of the .child(email) bit and use push to create the records.
var user_id = myDataRef.push({email: email, beta_key: false}).name();
The first thing to ask is whether you actually want to store the users by email. Generally, an ID is going to be much more useful (they may change their email later, in which case you have to go re-key all their user data in the system).
If that's a requirement, then you're either going to have to hash them or sanitize them. For example:
// replace all forbidden characters with something that won't appear in the email address
var key = email.replace(/[.$\[\]\/#]/, ','/);
myDataRef.child(key).set({email: email, beta_key: false});

Quality Center Filters and Favorites Action

I am trying to change the filters in the display of the current user in the Defects module.
I have set the "tdc.BUGFactory.Filter" object with my filter and i can access the data, but i cannot force it to be displayed to the user! any idea on how to do that?
If i use a SQL command to store it in the common settings table, would it be possible to call an action to load the "Favorites" view i created to the user?
Thanks,
Achraf
================================================================
I found the answer, however stackoverflow doesn't allow me to post it:
I fonud the answer through SQA Forums, to force a filter you use the following
Set defectFilter = tDConenction.BugFactory.Filter ' Example to set a filter criteria
defectFilter.Field ("BG_DETECION_DATE") = "[Today]"
SetDefectsFilter defectFilter.Text
Set defectFilter = Nothing
There is also a function called GetDefectsFilter() which gets the current filter

InfoPath autonumber field

I am designing an infopath (Change Request) form:
1)How can i add a text box that automaticaly increments to the next number when a new form is created (adding a new Change Request form to the form library).
2)How do i retrieve information from an existing form to the new form.
NOTE: The field is not inside a repeating table. I need to generate the next Change Request number on each new Change Request form.
TIA!
There is no build-in way to do this, but there are several ways to achieve what you want (Database query or SPList query). But this kind of request somehow smells like a workaround for an other problem.
Common cases for increasing numbers are:
unique IDs
count the Requests
make referable by external list (same as ID)
make IDs guessable (time stamps are not)
If you need an ID: In most cases you are not forced to use integer IDs. Simply use the form title as a natural ID. (e.g. customer + timestamp)
If you need guessable IDs, you need them because an external system wants to access or refer to the request. In that case try to change the pull-direction into a push-direction (e.g. by using workflows) or let your other system provide a "getID" function that can be called by your form to obtain a known ID (no guessing needed).
Anyway - for me, it looks like you want to achieve this to solve some other problem. Maybe there are different solutions for that problem too?
You could enter a token in your text-titles on the form where you want autonumbering, such as #num#, and then use javascript or jquery to find those tokens and replace them with incremented numbers.
The drawback to this is that if you exported the list to excel, the tokens would not get translated to numbers. But it is a good solution for on-screen rendering.
Use Firebug to figure out the class of the container housing your autonumber tags.
Maybe you could do something like this:
function TokenReplacement(){
var ClassName = 'ms-formlabel';
var elements = new Array();
var elements = document.getElementsByTagName('td');
var numerator=0;
//Now do find and replace on everything else
for(var e=0;e<elements.length;e++){
thiselement = elements[e];
if(thiselement.className == ClassName){
//autonumber the questions by replacing the #num# token
if(thiselement.innerHTML.search('#num#') > -1){
numerator++
var replacenum = "<b>" + numerator + ". </b>";
thiselement.innerHTML = elements[e].innerHTML.replace('#num#',replacenum);
}
}
}
}

Resources