how to escape ampersand in query payload in IDE - bixby

I have to add the following string to a restdb query:
&sort=_changed%26dir=-1
so it will look like this (which works in Postman):
{"identifier": "impeachmentsage"}&sort=_changed&dir=-1
I have tried several ways of escaping the &, including %26 and the ampersand character followed by amp; , but no matter what I get an error message complaining about the presence of the &. https://bixbydevelopers.com/dev/docs/reference/JavaScriptAPI/http#http-options
function getNewsByName(altBrainsNames, $vivContext) {
console.log('viv', $vivContext, altBrainsNames)
dashbot.logIncoming("Getting news by name", "GetNewsByName", $vivContext, altBrainsNames);
const url = properties.get("config", "baseUrl") + "content"
console.log("i got to restdb.js and the url is ", url);
console.log("AltBrainsNames is", altBrainsNames)
ampersand = "&"
const query = {
apikey: properties.get("secret", "apiKey"),
q: "{\"" + "identifier" + "\":\"" + altBrainsNames + "\"}" + ampersand+ "sort=_changed%26dir=-1"
}
console.log("query", query)
const options = {
format: "json",
query: query,
cacheTime: 0
}
Tried a couple of additional things.
var s = "sort=_changed%26dir=-1"
const query = {
apikey: properties.get("secret", "apiKey"),
q: "{\"" + "identifier" + "\":\"" + altBrainsNames + "\"}",
s: "sort=_changed%26dir=-1"
}
This gets closer and emits the ampersand, but the s= following it is extraneous.
UPDATE:
so I also tried constructing the complete URL and submitting it via the url parameter in getURL, bypassing the query option.
const url = properties.get("config", "baseUrl") + "content";
const q = "q={\"" + "identifier" + "\":\"" + altBrainsNames + "\"}";
const ampersand = encodeURIComponent("&");
submiturl = url + "\?" + q + ampersand + "sort=_changed" + ampersand + "dir=-1"
console.log('submit url is', submiturl)
const options = {
format: "json",
headers: {
'apikey': properties.get("secret", "apiKey"),
},
cacheTime: 0
}
console.log(options)
const response = http.getUrl(submiturl, options)
This produces a 400 error "unexpected & in JSON at column 32".
I now suspect that the fundamental problem is that getURL insists that the query string must be a matched key/value pair, while restdb's syntax provides for an unbalanced blank/value pair, i.e. &sort... rather than &s=sort. If this is the case, either getURL or restdb needs to change something...

Thanks so much to #rogerkibbe! Posting my final code here as there are one or two minor tweaks to get it in exactly the right format for restdb.
const url = properties.get("config", "baseUrl") + "content";
const q = "{\"" + "identifier" + "\":\"" + altBrainsNames + "\"}";
const options = {
format: "json",
headers: {
'apikey': properties.get("secret", "apiKey"),
},
query: {
q: q,
//identifier: "impeachmentsage",
sort: "_changed",
dir: -1,
//blank: "",
//withAmper: "hello&world"
},
cacheTime: 0
}

Your URL query parameters should just be a JSON object, "query" which is in the options object - Bixby will take care of all the escaping etc needed
For example:
let url = "https://postman-echo.com/get"
let options = {
format: 'json',
query: {
identifier: "impeachmentsage",
sorts: "_changed",
dir: -1,
blank: "",
withAmper: "hello&world"
}
};
let response = http.getUrl(url, options)
console.log ("response = " + JSON.stringify(response));
Results in the following URL being called
https://postman-echo.com/get?identifier=impeachmentsage&sorts=_changed&dir=-1&blank=&withAmper=hello%26world
I added "blank" as an example of passing an empty string/null and "withAmper" showing Bixby does any necessary escaping for you.
FYI - if you ever need to escape a URL, the build in Javascript encodeURI works well

Related

I'm sending a generated pdf from my server to the client as a base64 pdf string. I'm trying to print it on the client side using printJS

I'm generating a report using fluentreports on my server and sending the base64 pdf string to the client on the callback. On the client once he/she receives the base64 string, I am required to print out this pdf string as a pdf which I am trying to accomplish using printJS. I also tried pdfMake but neither one wanted to work. If I console.log the base64 string and click on it, the pdf opens beautifully in the next tab but once I try to print it using printJS or pdfMake it opens a new tab and automatically closes it without doing anything. Is there any other way I could accomplish this? I've tried a lot of things already from reading up on other peoples' issues online and haven't gotten anywhere. Is there any library out there that can create a PDF document using a base64 pdf string so that I can use printJS to print out the document?
Function on the client that sends info to the server and receives back the pdf string:
submit: function () {
this.$Socket.emit('addrepair', {
CustomerID: this.$route.params.Customer.CustomerID,
Problem: this.problem,
BrandID: this.brand,
TypeID: this.type,
Model: this.model,
ColorID: this.color,
Warranty: this.convertbool(this.warranty),
Purchased: this.convertbool(this.purchase),
RushService: this.convertbool(this.rush),
DateReceived: this.datereceived,
UserID: this.UserID
}, (data) => {
if(data.authenticated==true)
{
//window.open(data.pdf)
//pdfMake.createPdf(this.convertDataURIToBinary(data.pdf)).print()
console.log(data.pdf)
printJS({printable: data.pdf, type: 'pdf'})
this.jobdialog=true
}
})
Function on the server that serves the pdf base64 string:
socket.on('addrepair', (data, callbackfn) => {
let query="INSERT INTO repair(CustomerID, Problem, BrandID, Model, ColorID, Warranty, Purchased, RushService, DateReceived, TypeID, UserID) VALUES (" + data.CustomerID + ", \'" + data.Problem + "\', " + data.BrandID + ", \'" + data.Model + "\', " + data.ColorID + ", " + data.Warranty + ", " + data.Purchased + ", " + data.RushService + ", \'" + data.DateReceived + "\', " + data.TypeID + ", " + data.UserID + ");"
con.query(query, function(err) {
if(err) {
throw err
}
else
{
query="SELECT RepairID, FirstName, LastName, Address, PhoneNumber, RushService, Purchased, DateReceived, Problem, Model, (SELECT Type from types WHERE repair.TypeID=types.TypeID) as Type, (SELECT Color from colors WHERE repair.ColorID=colors.ColorID) as Color, (SELECT Brand from brands WHERE repair.BrandID=brands.BrandID) as Brand, Warranty from repair INNER JOIN customer ON repair.CustomerID=customer.CustomerID WHERE repair.RepairID=(SELECT LAST_INSERT_ID())"
con.query(query, function(err, rows) {
if(err) {
throw err
}
else
{
var options = {
data: rows
}
//var myreport = new Report("buffer", options)
var myreport=new Report.Report("buffer", options)
.data(rows)
.pageHeader(repairheaderFunction)
.detail(repairdetailFunction)
.pageFooter(repairfooterFunction)
myreport.render(function (err, data) {
callbackfn({authenticated: true, pdf: 'data:application/pdf;base64,' + data.toString('base64')})
})
//callbackfn({authenticated: true, data: rows})
}
})
}
})
})
var repairheaderFunction = function(Report, data) {
};
var repairdetailFunction = function(Report, data) {
Report.print("#" + data.RepairID, {fontSize: 22, bold: true, underline:true, align: "center"});
Report.newLine(2);
Report.print('First Name: ' + data.FirstName + "\n")
Report.print('Last Name: ' + data.LastName + "\n")
Report.print('Address: ' + data.Address + "\n")
Report.print('Phone Number: ' + data.PhoneNumber + "\n")
Report.print('Brand: ' + data.Brand + "\n")
Report.print('Model: ' + data.Model + "\n")
Report.print('Color: ' + data.Color + "\n")
Report.print('Problem: ' + data.Problem + "\n")
Report.print('Date Received: ' + data.DateReceived.slice(15) + "\n")
/*.text('Last Name: [LastName]\n')
.text('Address: [Address]\n')
.text('Phone Number: [PhoneNumber]\n')
.text('Brand: [Brand]\n')
.text('Model: [Model]\n')
.text('Color: [Color]\n')
.text('Problem: [Problem]\n')
.text('Date Received: [DateReceived]', 1.75, 0, 1, 0.25, {
pattern: 'M/D/YY'
})*/
};
var repairfooterFunction = function(Report) {
Report.line(Report.currentX(), Report.maxY()-18, Report.maxX(), Report.maxY()-18);
Report.pageNumber({text: "Page {0} of {1}", footer: true, align: "right"});
Report.print("Printed: "+(new Date().toLocaleDateString()), {y: Report.maxY()-14, align: "left"});
};
Print.js is now supporting base64 PDF print.
Try this:
printJS({
printable: your_base64_data_string,
type: 'pdf'
base64: true
})
The documentation has been updated with an example printing a base64 PDF document.
http://printjs.crabbly.com#pdf
Was able to get this to work after a lot of playing around with the code and thinking of possible solutions. Generates the iframe, pulls up the print dialog using the autoprint property of the report and then deletes the iframe once the focus is on the document again using the 'mousemove' event
The code is below:
printIframe: function(url) {
var proxyIframe = document.createElement('iframe');
var body = document.getElementsByTagName('body')[0];
body.appendChild(proxyIframe);
proxyIframe.style.width = '100%';
proxyIframe.style.height = '100%';
proxyIframe.id='iframe'
proxyIframe.style.display = 'none';
var contentWindow = proxyIframe.contentWindow;
contentWindow.document.open();
// Set dimensions according to your needs.
// You may need to calculate the dynamically after the content has loaded
contentWindow.document.write('<iframe src="' + url + '" width="1000" height="1800" frameborder="0" marginheight="0" marginwidth="0">');
contentWindow.document.close();
var x=0
var func=function (event) {
if(x===0)
{
body.removeChild(proxyIframe)
++x
}
else
{
document.removeEventListener('mousemove', func)
}
}
contentWindow.document.body.onload=() => {
contentWindow.document.body.focus()
setTimeout(()=>{
document.addEventListener('mousemove', func)
}, 5000)
}
},

How to pass date variable in uri for Microsoft graph request?

I'm trying to get back a list of calendar events with Microsoft Graph API but having problems with passing date variable in the query parameters.
If I hardcode the uri value to:
uri: 'https://graph.microsoft.com/beta/me/calendar/events?$filter=start/dateTime ge ' + `'2018-12-10T19:30:34.654Z'`,
then the request works. But if I try to pass the date variable with toISOString, I get an error. I've tried with or without backticks, and calling toISOString in the uri value and in the nextMonday function. Still doesn't work. Anyone have any ideas? Thanks!
function nextMonday(date){
var monday = new Date(date);
monday.setDate(monday.getDate() + (1 + 7 - monday.getDay()) % 7);
return monday.toISOString();
}
let date = new Date();
let m = nextMonday(date);
const options = {
uri: 'https://graph.microsoft.com/beta/me/calendar/events?$filter=start/dateTime ge ' + `m`,
auth: {
bearer: token,
},
headers: {
'content-type': 'application/json'
},
json: true // Automatically parses the JSON string in the response
};
You need to (1) use ${m} to add the value and (2) wrap it in single quotes.
uri: https://graph.microsoft.com/beta/me/calendar/events?$filter=start/dateTime ge '${m}',

Invalid URL Error in alamofire in IOS while passing right url

What I want to do is to get json data from below url
https://query.yahooapis.com/v1/public/yql?q=select * from
weather.forecast where woeid in (select woeid from geo.places(1) where
text='seoul,kr') and u='c'&format=json
which works great if type it on browser.
but it dosen't work on alamofire...
I think it's because of ' mark
as I can see \ is embedded saying FATAL invalid url
let rrrr="https://query.yahooapis.com/v1/public/yql?q=select * from weather.forecast where woeid in (select woeid from geo.places(1) where text='seoul,kr') and u='c'&format=json"
print(rrrr)
let alamo=Alamofire.request(rrrr,method:.get)
alamo.responseJSON {
response in
if response.data != nil {
print("not null")
let json = JSON(data: response.data!)
print(json)
print("not null21")
print(response)
print("not null12")
print(response.data!)
Log result is as follows
https://query.yahooapis.com/v1/public/yql?q=select * from weather.forecast where woeid in (select woeid from geo.places(1) where text='seoul,kr') and u='c'&format=json
not null
null
not null21
FAILURE: invalidURL("https://query.yahooapis.com/v1/public/yql?q=select * from weather.forecast where woeid in (select woeid from geo.places(1) where text=\'seoul,kr\') and u=\'c\'&format=json")
not null12
As I have seen your URL string contains the spaces in select query.
Actually, alamofire doesn't support URL string with spaces. Try to replace the URL string spaces with %20 (i.e encoded character space).
OR you can use URL encoding with the Alamofire request.
Hope it will help!
I use this:
enum ConsultOfficesServiceEndpoints : String {
case getProposedPeople = "aaa/bbb/ccc/%d/"
}
.
.
.
func getProposedPeople(_ name: String, success: #escaping SuccessResponse,failure: #escaping FailureResponse){
var paramWithSpaces = ""
var lines = name.components(separatedBy: " ")
var numlines = lines.count
var i = 0
if numlines > 1{
while i < (numlines - 1) {
paramWithSpaces = paramWithSpaces + lines[i] + "%20"
i = i+1
}
paramWithSpaces = paramWithSpaces + lines[numlines - 1]
}else{
paramWithSpaces = name
}
self.GET(withEndpoint: ConsultOfficesServiceEndpoints.getProposedPeople.rawValue.replacingOccurrences(of: "%d", with: paramWithSpaces), params: nil, headers: nil, success: success, failure: failure)
}

SharePoint Hosted App - Creating cascaded drop down on hosted web lists

I have created a SharePoint Hosted App(Javascript Object Model) that creates lists on the host web.
I need to put some javascript into new and edit forms in order to create the cascaded drop down effect on 2 lookup fields.
Here is how I create the lists and the fields for it:
// Create a new list on host web
var createList = function (listTitle, onSuccess, onFieldsReady) {
var listCreationInfo = new SP.ListCreationInformation();
listCreationInfo.set_title(listTitle);
listCreationInfo.set_templateType(SP.ListTemplateType.genericList);
var lists = hostWeb.get_lists();
var newList = lists.add(listCreationInfo);
currentContext.load(newList);
currentContext.executeQueryAsync(onSuccess(newList, onFieldsReady), onListCreationFail);
}
// Create a new field on a list
var createField = function (list, fieldType, fieldName, fieldDisplayName, fieldRequired, onSuccess) {
var fields = list.get_fields();
var fieldXml = "<Field Type='" + fieldType + "' Required='" + fieldRequired + "' DisplayName='" + fieldDisplayName + "' Name='" + fieldName + "'></Field>";
var createdField = fields.addFieldAsXml(fieldXml, true, SP.AddFieldOptions.addFieldInternalNameHint | SP.AddFieldOptions.addFieldToDefaultView);
currentContext.load(createdField);
currentContext.executeQueryAsync(onSuccess, onProvisionFieldFail);
}
Can you please give me some advise?
Regards,
Marian
You should consider ditching the idea of using NewForm and Editform.aspx. Just write your own form and use the JSOM or WebApi to add/edit list items.
Sample code for adding item to a list:
jQuery.ajax({
url: "http://<site url>/_api/web/lists/GetByTitle('Test')",
type: "POST",
data: JSON.stringify({ '__metadata': { 'type': 'SP.List' }, 'Title': 'New title' }),
headers: {
"X-HTTP-Method":"MERGE",
"accept": "application/json;odata=verbose",
"content-type": "application/json;odata=verbose",
"content-length": <length of post body>,
"X-RequestDigest": $("#__REQUESTDIGEST").val(),
"IF-MATCH": "*"
},
success: doSuccess,
error: doError
});
Reference: http://msdn.microsoft.com/en-us/library/office/jj164022(v=office.15).aspx
Try this.
var clientContext = new SP.ClientContext.get_current();
var list = clientContext.get_web().get_lists().getByTitle('ListName');
if(list) {
var fldCollection = list.get_fields();
var fieldLookup1 = clientContext.castTo(
fldCollection.addFieldAsXml('<Field Name="FieldName1" Type="Lookup" DisplayName="My Lookup Field 1" List="Lists/MyLookupList" ShowField="Title" />', true, SP.AddFieldOptions.addToDefaultContentType),
SP.FieldLookup
);
fieldLookup1.set_title("MyLookupField1");
fieldLookup1.set_description("Lookup field 1 description");
fieldLookup1.update();
list.update();
clientContext.executeQueryAsync(
Function.createDelegate(this, this.onQuerySucceeded),
Function.createDelegate(this, this.onQueryFailed)
);
}
Please let me know if it works ;)
Have a nice day!

Dialogs OData Set name?

Ok in crm 2011 using Odata Query - if a workflows Odata Set name is AsyncOperationSet What is the equivalent for a dialog?
I have tried to figure this out with no luck
Please help
Thank you
P.s I need to get the dialogs id from its name
When searching for a dialog to launch via javascript:
Category = 1 (Dialog)
Type = 1 (Definition) - This is important if trying to call a dialog from javascript!
Solution:
triggerDialog = function (name, entityName, recordId) {
var dialogId = "";
var request = Xrm.Page.context.getServerUrl() + "/XRMServices/2011/OrganizationData.svc/WorkflowSet?$select=Name,WorkflowId&$filter=Type/Value eq 1 and Category/Value eq 1 and Name eq '"+name+"'";
$.ajax({
type: "GET",
contentType: "application/json; charset=utf-8",
datatype: "json",
url: request,
async: false,
beforeSend: function (XMLHttpRequest) {
XMLHttpRequest.setRequestHeader("Accept", "application/json");
},
success: function (data, textStatus, XmlHttpRequest) {
if (data.d.results.length > 0) {
dialogId = data.d.results[0].WorkflowId;
}
},
error: function (XmlHttpRequest, textStatus, errorThrown) {
/*Error Occurred*/
}
});
var serverUrl = Xrm.Page.context.getServerUrl();
window.showModalDialog(
serverUrl + "/cs/dialog/rundialog.aspx?DialogId=" + encodeURIComponent(dialogId) + "&EntityName=" + encodeURIComponent(entityName) + "&ObjectId=" + encodeURIComponent(recordId), null, "dialogHeight:600px;dialogWidth:800px;center:yes; resizable:1;maximize:1;minimize:1;status:no;scroll:no");
Hope this helps
Just for your information. AsyncOperation is not instances of workflows only. It could be anything that is executed asynchronously (async plugins, calculating of matchcodes for dupdetection rules and many other).
Not sure what exactly do you want to get from Odata. What exactly do you need to get? If you need an instance of dialog - you will need to use AsyncOperation as well.

Resources