Replace operation breaks images in table OneNote (Graph API) - microsoft-graph-api

I have todo inside table. Also table contains image. Page screenshot
I need to mark "A" as completed. According to a documentation I should perform replace action for whole table.
First I call GET /me/onenote/pages/{pageId}/content?includeIDs=true to find right id of table (see "Page content before the PATCH" ⇩).
Then I send PATCH /me/onenote/pages/{pageId}/content with body:
[
{
"target": "table:{20c31cfe-9865-441d-9dbc-d8c53922d8f5}{21}",
"action": "replace",
"content": "<table border=\"1\"><tr><td><p data-tag=\"to-do:completed\">A</p></td><td><img src=\"https://graph.microsoft.com/v1.0/me/onenote/resources/1-66692d9b618447e9ad0d191137fcf91c!1-9857064f-8cbd-4b01-a41d-10e231bd6349/$value\"/></td></tr></table>"
}
]
API responds 204, and "A" is completed now. But image has been broken: updated page
How can I update a table that contains images?
Page content before the PATCH (Graph API response)
<html lang="en-US">
<head>
<title>Test 1</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="created" content="2018-10-08T12:03:00.0000000" />
</head>
<body data-absolute-enabled="true" style="font-family:Calibri;font-size:11pt">
<div id="div:{9f7149ca-3f9e-4275-8fa2-a51debcdb40c}{136}" style="position:absolute;left:48px;top:115px;width:624px">
<table id="table:{20c31cfe-9865-441d-9dbc-d8c53922d8f5}{21}" style="border:1px solid;border-collapse:collapse">
<tr id="tr:{20c31cfe-9865-441d-9dbc-d8c53922d8f5}{22}">
<td id="td:{20c31cfe-9865-441d-9dbc-d8c53922d8f5}{23}" style="border:1px solid">
<span lang="ru-RU" data-tag="to-do">A</span>
</td>
<td id="td:{20c31cfe-9865-441d-9dbc-d8c53922d8f5}{26}" style="border:1px solid">
<img id="img:{20c31cfe-9865-441d-9dbc-d8c53922d8f5}{54}" width="99" height="35" src="https://graph.microsoft.com/v1.0/users('0c2b9435-52c9-4480-a1d9-9faa92cecf51')/onenote/resources/1-66692d9b618447e9ad0d191137fcf91c!1-9857064f-8cbd-4b01-a41d-10e231bd6349/$value" data-src-type="image/png" data-fullres-src="https://graph.microsoft.com/v1.0/users('0c2b9435-52c9-4480-a1d9-9faa92cecf51')/onenote/resources/1-66692d9b618447e9ad0d191137fcf91c!1-9857064f-8cbd-4b01-a41d-10e231bd6349/$value" data-fullres-src-type="image/png" />
</td>
</tr>
</table>
</div>
</body>

Per the OneNote team, you need to do some transformation to the images before sending your PATCH.
When you do the GET for the page, the images come back with a src attribute like: https://graph.microsoft.com/v1.0/users('0c2b9435-52c9-4480-a1d9-9faa92cecf51')/onenote/resources/1-66692d9b618447e9ad0d191137fcf91c!1-9857064f-8cbd-4b01-a41d-10e231bd6349/$value. This value isn't actually a direct link to an image, but is a Graph request URL to get the image. This is the key problem.
Your app must make a GET on that URL to retrieve the image contents, then encode the binary image returned into base 64, then add that into the <img> tag. That should work around the problem.

Related

Can't access index.gsp in grails

I am new to grails and I am trying to access index page. After deleting the default homepage for grails, I getting the following error
404 App1/WEB-INF/grails-app/views/index.jsp
description The requested resource is not available.
I checked UrlMapping and view is set to index
"/"(view:"/index")
"500"(view:'/error')
My controller class
package App1grailsapp
class TeamController {
def index() { }
def teams()
{
[teams:Team.list()]
}
}
And I have two gsp pages,
index
<!--
To change this license header, choose License Headers in Project Properties.
To change this template file, choose Tools | Templates
and open the template in the editor.
-->
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Sample title</title>
</head>
<body>
<h2><g:message code="welcome"/></h2>
<ul>
<li><g:link action="teams">Display all teams</g:link></li>
</ul>
</body>
</html>
and teams
<html>
<head>
<meta name="layout" content="main">
<title>Teams</title>
</head>
<body>
<h2>Teams:</h2>
<table>
<tr>
<thead>
<th>Name</th>
</thead>
</tr>
<g:each var="team" in="${teams}">
<tr>
<td>${team.name}</td>
</tr>
</g:each>
</table>
</body>
</html>
I don't understand why index.gsp page is not being shown?
View resolution for Grails is based on convention. Each controller has a directory under grails-app/views for their associated views. Unless you specify otherwise (via render) the view displayed will match the controller action name.
In your case you need to move your index.gsp to grails-app/views/ and rename your teams.gsp to index.gsp under grails-app/views/team.
Hope this helps. You may want to take a look at the documentation for further information and insight.
Also, you will need to specify what controller is used by the link to show all teams.
<li><g:link controller="team" action="index">Display all teams</g:link></li>

Document type does not allow element "link" here

First i got the error while validating my code in Sortsite as "Document type does not allow element "Style" here." So i removed style portion and kept in a new css sheet.
After that while validating, i got "Document type does not allow element "link" here." error.
here is the code:
<%#taglib prefix="s" uri="/struts-tags" %>
<%#taglib prefix="d" uri="/dror-tags" %>
<link href="<s:url value='/styles/menu.css' includeParams="none"/>"
rel="stylesheet" type="text/css" media="all"/>
<!-- Action URLs -->
<s:url id="dppUrl" namespace="/xyz" action="abc" includeParams="none"/>
<s:url id="dppUrl" namespace="/xyz" action="abc" includeParams="none"/>
<d:button value="Menu" submenuId="mainSubmenu" cssStyle="float: left;"/>
<div dojoType="dror:PopupMenu2" widgetId="mainSubmenu" submenuOverlap="0">
<div dojoType="dror:MenuItem2"
caption="xyz"
onclick="try { window.location = '${xyzUrl}'; } catch (e) { };">
</div>
</div>
Please help me in solving this issue.
The only valid location for that <link> tag in a HTML document is between the <head> and </head> tags. You're getting that error because that's not the case in your code.
From the HTML spec:
If the rel attribute is used, the element is restricted to the head element.

google chartapi custom html datasource query times out

I am simply trying to implement what I believe is google's example of a custom HTML data-source. I am clearly missing something but am unable to see it.
The goal is to have my default page retrieve a table's worth of data from my own data-source and chart it.
The error I receive is eventually I get a timeout dialog displayed.
I have two files default.htm and data.htm. For a period of time this will also be on the associated website. (www.ichoosewellness.com/chartapitest).
default.htm:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load('visualization', '1', { packages: ['corechart'] });
</script>
<script type="text/javascript">
function drawVisualization() {
// Replace the data source URL on next line with your data source URL.
var query = new google.visualization.Query('http://www.ichoosewellness.com/chartapitest/data.htm?tqx=reqId:1;out:html');
// Send the query with a callback function.
query.send(handleQueryResponse);
}
function handleQueryResponse(response) {
if (response.isError()) {
alert('Error in query: ' + response.getMessage() + ' ' + response.getDetailedMessage());
return;
}
var data = response.getDataTable();
// Create and draw the visualization.
var comboChart = new google.visualization.ComboChart(document.getElementById('chart_div'));
comboChart.draw();
var div = document.getElementById('chart_div');
div.style.backgroundColor = 'red';
}
google.setOnLoadCallback(drawVisualization);
var div = document.getElementById('chart_div');
div.style.backgroundColor = 'red';
</script>
</head>
<body>
<div id='chart_div' style="width: 500px; height: 250px; border: 1px solid green;">
</div>
</body>
</html>
data.htm
<html>
<body>
<table border='1' cellpadding='2' cellspacing='0'>
<tr style='font-weight: bold; background-color: #aaa;'>
<td>
label 1
</td>
<td>
label 2
</td>
</tr>
<tr bgcolor='#f0f0f0'>
<td align='right'>
1
</td>
<td>
a
</td>
</tr>
<tr bgcolor='#ffffff'>
<td align='right'>
2
</td>
<td>
b
</td>
</tr>
<tr bgcolor='#f0f0f0'>
<td align='right'>
3
</td>
<td>
c
</td>
</tr>
<tr bgcolor='#ffffff'>
<td align='right'>
4
</td>
<td>
d
</td>
</tr>
</table>
</body>
</html>
This question is pretty old now but I will add what I found out about it since I had a similar problem.
Basically I was trying to get google.visualization.Query() to call my WCF REST service and have it return a json dataTable. Every time the query executed, it would throw a timeout error even though the GET request executed successfully. The culprit turned out to be the formatting of the response string and cross site domain permissions.
The response format is very particular and would throw a timeout error if not correctly defined. You have to go over the response format with a fine tooth comb and read the detailed documentation below.
Here is the URL that explain in detail the proper format:
http://code.google.com/apis/chart/interactive/docs/dev/implementing_data_source.html1
Secondly don't forget about cross site domain permission. Because I was testing from localhost:63532 and calling the REST service located on localhost:63002 they were not the same domain and was not being queried. For testing I needed to add the the following to the response header.
Access-Control-Allow-Origin:http://localhost:63532
These two items were the key to getting past the timeout error.
In the case of your code calling HTML, if you read the linked documentation above there is a section in there describing HTML Response Format. Here is the relevant text:
If the request specifies out:html, the response should be an HTML page defining an HTML table with the data. This is useful for debugging your code, because the browser can render your result in a readable format directly. You cannot send a query for an HTML response using the google.visualization.Query object. You must make a query for an HTML response using custom code, or by typing a URL similar to this one in your browser:
Since in your code you are trying to do this:
var query = new google.visualization.Query('http://www.ichoosewellness.com/chartapitest/data.htm?tqx=reqId:1;out:html');
It seems from the documentation that this is not supported by the query function.

Grails g:include can it be done?

Im wondering if it is possible to use g:include to include only the body contents of a given page.
Say i have a main layout page as follows:
<html>
<head>
<title>My start page</title>
<g:layoutHead>
</head>
<body>
<g:layoutBody>
</body>
</html>
Then a main page (index.gsp)
<html>
<head>
<!-- main layout reference -->
<meta name="layout" content="main"/>
</head>
<body>
THIS IS MY INDEX BODY CONTENT WITH AN INCLUDE
<g:include controller="book" action="list"/>
<g:link controller="book" action="list">See the full list!</g:link>
</body>
</html>
And finally the book/list page
<html>
<head>
<!-- main layout reference -->
<meta name="layout" content="main"/>
</head>
<body>
<table>
<g:each in="${books}">
<tr>
<td>${it.author}</td>
<td>${it.title}</td>
<td>${it.price}</td>
</tr>
</g:each>
</table>
</body>
</html>
So what i want to achieve is that the main page (index.gsp) only includes the table defined in the book/list page. However, when i try this it includes the entire html defined (<html> tags and all).
is it possible to do this somehow? i've tried things like <g:include controller="book" action="list" view="someView.gsp"/> however this doesn't work. I really want to avoid having to add a book list logic to the "index controller" i want to reuse my existing controller.
I can't be the first person out there having this usecase, what solutions have you guys come up with?
You can use the applyLayout tag. Simply create an empty.gsp layout with only:
<g:layoutBody/>
And then decorate your include tag with applyLayout:
<g:applyLayout name="empty">
<g:include controller="book" action="list"/>
</g:applyLayout>
See the entry on the Grails guide for further reference.
This is IMHO directly not possible. An idea would be to create a custom tag based on g:include, that strips out parts of the code by e.g. an xpath expression. I'm not aware that this already exists somewhere.
An alternative would be to refactor the body part of book's list.gsp into a template and reference that template from index.gsp using g:render. But this means that the data model has to be available in index.gsp context since g:render does not invoke a controller.
Side note: when using g:include it's a good idea to use the springcache plugin for page fragment caching.
Yes, but you need you need one more level in there. Look at Grails templates. Essentially, you'd have a template: _books.gsp containing:
<table>
<g:each in="${books}">
<tr>
<td>${it.author}</td>
<td>${it.title}</td>
<td>${it.price}</td>
</tr>
</g:each>
</table>
Then your index would be:
<html>
<head>
<!-- main layout reference -->
<meta name="layout" content="main"/>
</head>
<body>
THIS IS MY INDEX BODY CONTENT WITH AN INCLUDE
<g:render template="books">
<g:link controller="book" action="list">See the full list!</g:link>
</body>
</html>
And your list would be:
<html>
<head>
<!-- main layout reference -->
<meta name="layout" content="main"/>
</head>
<body>
<g:render template="books" />
</body>
</html>
(My syntax may not be 100% right, since it's been a couple months since I've done this, but the idea behind templates are short, reusable pieces of GSP code that aren't meant to be displayed on their own.

How do I pass a variable into grails template from a Layout file?

So I have a navigation template (/common/_navigation.gsp) that is getting rendered in the Grails projects main Layout file (/layouts/main.gsp). How do I pass some kind of variable/parameter/arg from the individual view files to layout and eventually into the navigation template? I just want the right tab to be highlighted when I'm on a page.
(We've already tried using the Grails Navigation Plugin. Since we have different tabs that point to the same controllers (same view, different filter) it breaks down.)
I do this pattern all the time. In my view, I can attach a property to the page either manually or by using the parameter tag in the view that I'm rendering. Its not documented in the Grails user guide, but its super handy.
<parameter name="foo" value="bar" />
Then I would access the page property by using the pageProperty tag.
<g:set var="activeNavItem" value="${pageProperty(name: 'page.foo')}"/>
The layout doesn't need to handle this variable at all :-)
just use the model parameter
for Example:
view:
<g:render template="../path/template" model="[header:'test', headers:['a','b'], values:[['a':1,'b':2],['a':3,'b':4]] ]"/>
_template:
<br/>
<h3>${header}</h3>
<table>
<thead>
<tr>
<g:each in ="${headers}" var="he">
<th>${he}</th>
</g:each>
</tr>
</thead>
<tbody>
<g:each in ="${values}" var="v">
<tr>
<g:each in ="${headers}" var="h">
<td>${v[h]}</td>
</g:each>
</tr>
</g:each>
</tbody>
</table>
I use an arguably simpler method. Just define a variable at request scope in the individual view before you call your layout. It will be available in all templates used in the request, including the layout and any called via <g:render>
<g:set var="SOMEVARIABLE" value="SOMEVALUE" scope="request"/>
<meta name="layout" content="yourlayout">
Then just reference the variable as you would any other in your layout or other templates pulled in by your view
${SOMEVARIABLE} or <g:if test="${SOMEVARIABLE}">, etc., etc
You'd need to use a page property: http://grails.org/doc/1.1.1/ref/Tags/pageProperty.html
Then pass it into the render tag using the model param.
cheers
Lee
The pattern I like, uses the pageProperty as follows. In the layout, I reference the pageProperty like so:
The layout gsp
<body id="${pageProperty(name: 'page.pageType')}">
<g:render template="/layouts/header" />
<g:layoutBody/>
<g:render template="/layouts/copyright" />
</div>
... and within the <head> section of the specific gsp page (I found that it did NOT work outside the head section), I declare the value like so:
The page gsp
<head>
<meta name="layout" content="main"/>
<parameter name="pageType" value="homePg" />
</head>
Resulting HTML
<body id="homePg">
... header, body and footer ...
</body>
In addition, I can inject a value from the controller model into pageProperty like so:
Controller
def index() {
model: [modelPageType: 'adminPg']
}
The layout gsp (using the same layout as above)
<body id="${pageProperty(name: 'page.pageType')}">
<g:render template="/layouts/header" />
<g:layoutBody/>
<g:render template="/layouts/copyright" />
</div>
The page gsp
<head>
<meta name="layout" content="main"/>
<parameter name="pageType" value="${modelPageType}" />
</head>
Resulting HTML
<body id="adminPg">
... header, body and footer ...
</body>
You can simply reach any variable in any template in the page by getting it from params.
Just type ${params.variable} in layout and you will get your variable.
Based on my readings, I think its not a good practice to pass variables to your layout. Model variables are accessible in your view. I think layouts should be used only to specify the structure of the page while views can be used to fill in the content.

Resources