I have a button in a google-app-maker page, it's function is to sending Invoice by email. So once this button clicked, it will do two function.
1. Sending invoice by email.
2. Change status of EmailStatus to 'YES'.
/* var widgets = widget.parent.descendants; */
var to = "webmaster#myemail.com";
var subject = "Prepare Invoice : " + widget.datasource.item.Client_Name;
var msg = "Please Prepare Invoice for " + "\n\nClient Name : " +
widget.datasource.item.Client_Name + "\n\nService : " +
widget.datasource.item.Service + "\n\nCase : " +
widget.datasource.item.Subjects + "\n\nScope :" +
widget.datasource.item.Scope + "\n\nSubject : " +
widget.datasource.item.Subjects + "\n\nStart :" +
widget.datasource.item.Start + "\n\nInterim : " +
widget.datasource.item.Interim + "\n\nStatus :" +
widget.datasource.item.Statusx + "\n\nCA : " +
widget.datasource.item.Client_Ref + "\n\nBilling : " +
widget.datasource.item.Billing + "\n\nFee VS : " +
widget.datasource.item.Fee_VS + "\n\nFee VI" +
widget.datasource.item.Fee_VI + "\n\nNotes : " +
widget.datasource.item.Notes + "\n\nPrep Invoice : " +
widget.datasource.item.Prep_Invoice + "\n\nInvoiced : " +
widget.datasource.item.Prep_Invoice + "\n\nInvoice Number : " +
widget.datasource.item.Invoice_Number;
SendEmail(to, subject, msg);
widget.datasource.modes.create.item.EmailStatus = 'YES';
There's no problem with sending email, but for EmailStatus change to field have problem. It can not change value from NULL to 'YES'. Do you have any idea how to solved it ?
Thanks
Here is a scenario how to handle this assuming that your EmailStatus is just field in the same model/datasource as where you have all of your invoice information.
Delete this line of code:
widget.datasource.modes.create.item.EmailStatus = 'YES';
Change this line of code:
SendEmail(to, subject, message);
to:
SendEmail(to, subject, message, widget.datasource.item);
Change your client send email function to this:
function SendEmail(to, subject, message, item) {
google.script.run
.withSuccessHandler(function() {
item.EmailStatus = 'YES';
})
.withFailureHandler(function(error) {
//include a failure message popup or something here
})
.ServerSendEmailFunction(to, subject, message);
}
Hope this helps and solves your problem.
Is "EmailStatus" a field in the datasource of the widget, or is it a field in a different datasource? If it is actually a field in a different datasource/model, then you have to specify which record in that other datasource you want to connect to (in this case, the record called "Yes").
I'd recommend creating another server script function to set the status to "Yes" - here's the instructions for doing that: https://developers.google.com/appmaker/models/relations#server_script
Then call this new function in your success handler for the SendEmail function.
Related
I am unable to get image from a URL that is an XML response. i used following code to fetch information from this URL including image too since i thought that i will get image although the xml response has image url but i am getting image URL instead of image.
Why is it so? kindly guide me! i am a newbie to xamarin forms.
URl : https://www.goodreads.com/book/title.xml?key=Uxb0zPb86N4STVy2ECWYA&title=Dune
CODE:
XElement search_result =(from xFi in Xdoc.Descendants("book")
where (xFi.Element("country_code").Value == "PK") || (xFi.Element("language_code").Value == "eng")
select xFi).FirstOrDefault();
if (search_result != null)
{ search.Text=
"Title: " + search_result.Element("title").Value + "\n" +
"Average Ratings: " + search_result.Element("average_rating").Value + "\n" +
"ISBN: " + search_result.Element("isbn").Value + "\n" +
"PUBLICATION YEAR: " + search_result.Element("publication_year").Value +
"\n" +"PUBLISHER: " + search_result.Element("publisher").Value + "\n" +
"DESCRIPTION: " + "\n" + search_result.Element("description").Value + "\n"
+ "IMAGE: " + "\n" + search_result.Element("image_url").Value + "\n";
} else
{
search.Text = "Found Nothing";
}
assuming I have an Image control on my page named "bookimage"
var url = search_result.Element("image_url").Value;
bookimage.Source = ImageSource.FromUri(new Uri(url));
this is clearly explained in the docs
I have a simple ASP.NET MVC application, where our users have a table which has some options to edit some settings.
This table is build dynamically using jQuery since this is some legacy code. The code to make the table is:
function setInvoiceTable(result) {
result.OverduesPaged.forEach(function (item, index) {
var externalName = 'OverduesPaged[' + index + '].ExternalInvoiceGuid';
var debtorName = 'OverduesPaged[' + index + '].Debtor';
var visibleName = 'OverduesPaged[' + index + '].IsSelected';
var externalInvoiceGuidField = '<input type=\'hidden\' value=\'' + item.ExternalInvoiceGuid + '\' name=\'' + externalName+ '\' />';
var debtorField = '<input type=\'hidden\' value=\'' + item.Debtor + '\' name=\'' + debtorName + '\' />';
var invisibleField = '<input type=\'hidden\' value=\'false\' name=\'' + visibleName + '\' id=\'' + visibleName + '\' /></label>';
var visibleField = '<label><input type=\'checkbox\' value=\'true\' name=\'' + visibleName + '\' id=\'' + visibleName + '\' /> Start sag';
var insertStr = "<tr>" +
"<td>" + externalInvoiceGuidField + debtorField + visibleField + invisibleField + "</td>" +
"<td>" + item.InvoiceId + "</td>" +
"<td>" + item.Debtor + "</td>" +
"<td>" + item.DateString +"</td>" +
"<td>" + item.DaysSinceDueString +"</td>" +
"<td>" + item.GrossAmountString + "</td>" +
"<td>" + item.RemainderAmountString + "</td>" +
"</tr>";
$('#accounting_invoices_table').append(insertStr);
});
}
When I POST, this works perfectly for us. We have an endpoint in our controller which has this signature:
[System.Web.Mvc.HttpPost]
public ActionResult StartDebtCollectionCases(UpcomingDashboardViewModel vm)
{
// code
}
The collection I'm building is the OverduesPaged which is a part of our view model:
public class UpcomingDashboardViewModel
{
public List<OverdueUpcomingInvoiceViewModel> OverduesPaged { get; set; }
// more stuff not relevant to question
}
This is my challenge:
I've added a css class to the <tr> row like this:
// new code added
var removeClass = 'ok';
if (item.IsAlreadyCase) {
visibleField = '<label type="text">Allerede startet</label>';
removeClass = 'remove';
} else if (item.IsBlocked) {
visibleField = '<label type="text">Sat i bero</label>';
removeClass = 'remove';
}
else if (item.Currency != "DKK") {
visibleField = '<label type="text">Faktura skal være dansk valuta</label>';
removeClass = 'remove';
}
var insertStr = "<tr class='" + removeClass + "'>" +
"<td>" + externalInvoiceGuidField + debtorField + visibleField + invisibleField + "</td>" +
// rest of code from above
Now I end up with a table exactly like before, but with a class which is either OK or REMOVE.
However, when I now do the POST, the whole collection, OverduesPaged, is null/empty:
I tried to add the class to the <td> instead, but then the collection was null/empty.
Any ideas what is wrong here?
The issue is not related to adding the class name itself, but rather the invalid html that you generating if ant of the code in the if or else if blocks are executed. In those blocks you are creating <label> element with a closing tag, but no input (its not clear if you need the checkbox or not in those cases), so when you combine visibleField + invisibleField you get unbalanced <label> tags (visibleField has opening and closing tags, but invisibleField only has a closing </label> tag.
You code in the if blocks to generate visibleField would need to be similar to what you generate in the original code - i.e. just an opening <label> with the html for the checkbox.
As you have acknowledged in the comments, this is very fragile and error prone code that is difficult to debug. As you are intending to rewrite it, consider returning a partial view in your ajax call (that is strongly bound to the model), or if you need to return Json, then consider a hidden template (outside the <form> tags) that you clone and update in the script, for example
<div id="newrow" style="display:none">
<tr>
<td>
<input class="invoice" type="hidden" name="OverduesPaged[#].ExternalInvoiceGuid value />
<input class="debtor" type="hidden" name="OverduesPaged[#].Debtor value />
....
</td>
....
</tr>
</div>
and then you script becomes
var table = $('#accounting_invoices_table');
result.OverduesPaged.forEach(function (item, index) {
var clone = $('#newrow').clone();
// Update indexer
clone.html($(clone).html().replace(/\[#\]/g, '[' + index + ']'));
// Update values
clone.find('.invoice').val(item.ExternalInvoiceGuid);
....
table.append(clone.html());
});
As a side note, your existing id attributes are invalid because they contain ., [ and ] characters (if you attempted to use these in jQuery selectors, they would fail (for example the . will be interpreted as a class name), so they should be omitted in the html
Consider the business process "Review and Approve (one or more reviewers) - Assign a review task to multiple reviewers".
When I choose reviewers I see only their properties cm:userName. How to display all the properties of the type cm:person?
For example:
cm:userName
cm:firstName
cm:middleName
cm:email
cm:organizationId
cm:jobtitle
cm:googleusername
And so on...
Instead of this container (part of the association.ftl):
...
<div id="${controlId}-currentValueDisplay" class="current-values"></div>
...
I would like to use table. IMHO for that I should override some parts of the
Alfresco.ObjectFinder, such as:
if (this.options.displayMode == "items")
{
Dom.get(this.id + "-currentValueDisplay").innerHTML = displayValue;
}
...etc. But how to display all the properties of the selected reviewers?
Let's say, this part:
displayValue +=
this.options.objectRenderer.renderItem(
item,
16,
"<div class='itemtype-" + $html(item.type) +
"' style='word-wrap: break-word;'>{icon} {name}</div>"
);
I assume that it's property is name
Ok, then where to find the mapping "property in object-finder : property in the person type"?
To display the companyname, email etc fields to you need to modify the following files in the repo side.
C:\Alfresco\tomcat\webapps\alfresco\WEB-INF\classes\alfresco\extension\templates\webscripts\org\alfresco\repository\forms\pickerresults.lib.js
C:\Alfresco\tomcat\webapps\alfresco\WEB-INF\classes\alfresco\extension\templates\webscripts\org\alfresco\repository\forms\pickerresults.lib.ftl
In the pickerresults.lib.js, I added the required extra properties in the CreatePersonResult(node) method.
function createPersonResult(node)
{
var personObject =
{
typeShort: node.typeShort,
isContainer: false,
properties: {},
displayPath: node.displayPath,
nodeRef: "" + node.nodeRef
}
// define properties for person
personObject.properties.userName = node.properties.userName;
personObject.properties.name = (node.properties.firstName ? node.properties.firstName + " " : "") +
(node.properties.lastName ? node.properties.lastName : "") +
" (" + node.properties.userName + ")";
personObject.properties.jobtitle = (node.properties.jobtitle ? node.properties.jobtitle : "");
//Add the extra properties here
personObject.properties.organization =(node.properties.organization ? node.properties.organization : "");
personObject.properties.googleusername =(node.properties.googleusername ? node.properties.googleusername : "");
return personObject;
}
In the pickerresults.lib.ftl, I added the extra properties to the result set, below to the "selectable" : ${row.selectable?string}</#if>
"nodeRef": "${row.item.nodeRef}"<#if row.selectable?exists>,
"selectable" : ${row.selectable?string}</#if>,
"company": "${row.item.properties.organization!""}",
"googleusername": "${row.item.properties.googleusername!""}",
"jobtitle": "${row.item.properties.jobtitle!""}"
Hope this helps you now.
Object-finder.js is used for different kind of objects like person, tags etc.
item.type is cm:person, but it doesn't have all the person of person object here. Refer the below image.
In one of my forms the answers are optional. How can I get it so that only the fields that have been filled in show on the email that the form sends out?
Code example:
sb.Append("<br /><br /><br />Email from: " + txtEmail.Text + "\n");
sb.Append("<br /> <br />Site Name : " + txtSiteName.Text + "\n");
sb.Append("<br />Contract number : " + txtContractno.Text + "\n");
sb.Append("<br />Department : " + txtDepartment.Text + "\n");
If no one puts in their department, I dont want the heading and blank space where the answer should go to appear on the email. However if the department is filled in on the form, then I do want it to appear on the email. What should I do?
Two simplest options would be:
if (!string.IsNullOrWhitespace(txtDepartment.Text))
sb.Append("<br />Department : " + txtDepartment.Text + "\n");
...
or
sb.Append((!string.IsNullOrWhitespace(txtDepartment.Text)) ? "<br />..." : string.Empty);
Of which the first is probably preferable as it skips the call to append completely if the string's not there.
This query will take input from three drop down box and a text box and it work's fine as expected.But my requirement is i need to use another three drop down box and a text in order to query much deeper.So,i need to hold the result of first query and also second query.How should i do.Help me.
That another three drop down box value is also obtained from the same variable's as 'operator','textvalue','querypass'.
function querymap()
{
var operator=document.getElementById('operatorstring').value.replace(/'/g, "\\'");
var textvalue=document.getElementById("text-value").value.replace(/'/g, "\\'");
var querypass=document.getElementById('query-pass').value.replace(/'/g, "\\'");
var searchStringe = document.getElementById('Search-stringe').value.replace(/'/g, "\\'");
var searchString = document.getElementById('search-string').value.replace(/'/g, "\\'");
{
layer.setQuery("SELECT 'geometry'," + querypass + " FROM " + tableid + " WHERE " + querypass + " " + operator + " '" + textvalue + "' AND VillageName = '"+ searchStringe+"'");
}
}
You can have as many AND conditions in your query as you want. No reason not to also check e.g. textvalue2, querypass2, searchString2, etc. and add them to your query. See this setQuery() answer which may give you some ideas. You'll need to set all your search conditions each time you call layer.setQuery() or layer.setOptions({query: ...});