Details
OS: Manjaro Linux
Node.js version: 10
npm version: 6
googleapis version: 51.0.0
Steps to reproduce
We are sending a google slide API request with updateShapeProperties:
"updateShapeProperties": {
"objectId": objectId,
"shapeProperties": {
"shapeBackgroundFill": {
"solidFill": {
"color": {
"rgbColor": {
"red": r,
"green": g,
"blue": b
}
},
"alpha": 1
}
},
"outline": {
"outlineFill": {
"solidFill": {
"color": {
"rgbColor": {
"red": 0,
"green": 0,
"blue": 0
}
},
"alpha": 0.1
}
},
},
"contentAlignment": "MIDDLE"
},
"fields": "*"
}
where objectId comes from one of any pageElement we get from slide.pageElements
We get a 400 response that states:
message: ""Invalid requests[2].updateShapeProperties: At least one field must be listed in 'fields'. (Use '*' to indicate all fields.)
This somehow used to work the past few months, and was wondering why it suddenly doesn't work right now. Did we have any changes or updates on the updateShapeProperties API?
I believe that [2] of Invalid requests[2].updateShapeProperties is the request body in your question. When I tested your request body, I could replicate your situation. The error message is At least one field must be listed in 'fields'. (Use '*' to indicate all fields.). When I tested "fields": "", I got the same error message. From this situation, I thought that it might be a bug.
When I searched this situation at the Google issue tracker, I found it. Ref
So as the current workaround, in order to avoid this error, in your request body, how about the following modification?
From:
"fields": "*"
To:
"fields": "shapeBackgroundFill,outline,contentAlignment"
Related
One can reproduce the problem.
Create new Spreadsheet.
Take SpreadsheetId (https://docs.google.com/spreadsheets/d/1rp11nqj0t0x1111111111111111111111111137Wj4XU/edit#gid=0, here it is 1rp11nqj0t0x1111111111111111111111111137Wj4XU)
Fill range A1:F15 with any content, let's use 'lorem ipsum' string, for instance.
Visit https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/batchUpdate
4.1 Look at right side where one can find "Try this method"
4.2 Fill field "spreadsheetId" with one you've taken on step 2.
4.3 Fill "Request body" with
{
"requests": [
{
"repeatCell": {
"cell": {
"userEnteredFormat": {
"textFormat": {
"strikethrough": true
}
}
},
"fields": "*",
"range": {
"startRowIndex": 2,
"endRowIndex": 2,
"startColumnIndex": 1,
"endColumnIndex": 3
}
}
}
]
}
4.4 Press "Execute" button at the bottom of right side.
5. Check you spreadshet.
6. No error, nothing happened.
What am I doing wrong ?
Modification points:
In your following request body, the values of startRowIndex and endRowIndex are the same. By this, this request body cannot be correctly worked. I thought that this might be the reason for your current issue of No error, nothing happened..
{
"requests":[
{
"repeatCell":{
"cell":{
"userEnteredFormat":{
"textFormat":{
"strikethrough":true
}
}
},
"fields":"*",
"range":{
"startRowIndex":2,
"endRowIndex":2,
"startColumnIndex":1,
"endColumnIndex":3
}
}
}
]
}
And also, in your request body, even when the above modification is reflected, the cell values are cleared by "fields":"*". Please be careful about this.
When these points are reflected in your request body, how about the following modification?
Modified request body:
{
"requests": [
{
"repeatCell": {
"cell": {
"userEnteredFormat": {
"textFormat": {
"strikethrough": true
}
}
},
"fields": "userEnteredFormat.textFormat.strikethrough",
"range": {
"startRowIndex": 0,
"endRowIndex": 15,
"startColumnIndex": 0,
"endColumnIndex": 6,
}
}
}
]
}
In this modified request body, from Fill range A1:F15 with any content, let's use 'lorem ipsum' string, for instance., the cells "A1:F15" are used. So, strikethrough is used for these cells.
In your request body, sheetId is not used. So, in this case, the 1st tab in Google Spreadsheet is used. Please be careful about this. If you want to use it for the specific sheet, please add the property of "sheetId": ### to range. ### is the sheet ID.
References:
RepeatCellRequest
GridRange
Trying to troubleshoot an error message my app gets after sending a batchUpdate request to Google Slides API
Invalid requests[19].updateTableCellProperties: Invalid field: table_cell_properties
The 19th request in the batch is the only updateTableCellProperties request I have. If I removing the 19th request from the batch, everything works fine.
Other requests which I run in this batchUpdate with no issues are are insertTableRows, deleteTableRow, insertText, updateParagraphStyle, updateTextStyle, updateTableColumnProperties. They all work on the same table, so I use the same objectId, but depending on the request I have to specify it as tableObjectId instead of objectId.
Unsure if I am generating a wrong request for the only updateTableCellProperties request I have, or if there is a problem in the Google Slides ruby gem itself, I tried sending just this updateTableCellProperties request from the Google Slides API explorer which has some validation on the request structure. So I sent this updateTableCellProperties batchUpdate request
{
"requests": [
{
"updateTableCellProperties": {
"objectId": "gf9d8fea71f_22_1",
"tableRange": {
"location": {
"columnIndex": 0,
"rowIndex": 1
}
},
"fields": "tableCellProperties",
"tableCellProperties": {
"tableCellBackgroundFill": {
"solidFill": {
"color": {
"themeColor": "LIGHT1"
}
}
}
}
}
}
]
}
And I got this error:
{
"error": {
"code": 400,
"message": "Invalid requests[0].updateTableCellProperties: Invalid field: table_cell_properties",
"status": "INVALID_ARGUMENT"
}
}
Why is this updateTableCellProperties request reported as invalid? I am also confused by the output of the error message as it mentions table_cell_properties in snake case, while the documentation only mentions tableCellProperties in camel case, and my request also only mentions tableCellProperties in camel case. I am only aware of the ruby gems translating between snake case and camel case, but this is not relevant to the API Explorer.
The error Invalid field: table_cell_properties originates from the erroneously specified fields property
See documentation:
fields
At least one field must be specified. The root tableCellProperties is implied and should not be specified. A single "*" can be used as short-hand for listing every field.
So you need to modify fields
from
"fields": "tableCellProperties"
to
"fields": "tableCellBackgroundFill.solidFill.color"
or to
"fields": "*"
There is a second problem with your request:
When specifying the table range, it is required to set the properties rowSpan and columnSpan.
A complete, correct request would be:
{
"requests": [
{
"updateTableCellProperties": {
"objectId": "gf9d8fea71f_22_1",
"tableRange": {
"location": {
"columnIndex": 0,
"rowIndex": 1
},
"rowSpan": 1,
"columnSpan": 1
},
"fields": "tableCellBackgroundFill.solidFill.color",
"tableCellProperties": {
"tableCellBackgroundFill": {
"solidFill": {
"color": {
"themeColor": "LIGHT1"
}
}
}
}
}
}
]
}
I would like to create a line with some point array with google-slide-api script. but I do not found any document about how to do it.
Then I create a line with scribble tool manually then read it by google-slide-api. I got below output:
- Slide #1 contains 1 elements.
elem #0 - {
"line": {
"lineProperties": {
"dashStyle": "SOLID",
"endArrow": "NONE",
"lineFill": {
"solidFill": {
"alpha": 1,
"color": {
"themeColor": "DARK2"
}
}
},
"startArrow": "NONE",
"weight": {
"magnitude": 9525,
"unit": "EMU"
}
}
},
"objectId": "gf0b4bb3376_0_2",
"size": {
"height": {
"magnitude": 786825,
"unit": "EMU"
},
"width": {
"magnitude": 763325,
"unit": "EMU"
}
},
"transform": {
"scaleX": 1,
"scaleY": 1,
"translateX": 1196175,
"translateY": 777044.3325,
"unit": "EMU"
}
}
That means google slide actual create it as a line type but nothing special to define the data points! then it's not possible to create the same from the output json data.
Answer:
Unfortunately, this isn't currently possible.
More Information:
As explained by Iamblichus in this answer, the Slides API does not support this kind of line, and as you have pointed out smoothing between separate lines does not work.
Feature Request:
You can however let Google know that this is a feature that is important for access to their APIs, and that you would like to request they implement it.
Google's Issue Tracker is a place for developers to report issues and make feature requests for their development services, I'd urge you to make a feature request there. The best component to file this under would be the Google Slides component, with the Feature Request template.
Problem:
I am unable to POST a transaction via the RESTful API generated by the composer-rest-server. I am receiving statusCode 422; the transaction instance is not valid. However, the same example works in the Playground.
Scenario:
I've set up a transaction called Offer in my .cto file which posts an offer to buy a house:
// Offer - Specifies an offer that a bidder places on a house listing with an associated price
transaction Offer {
o Double bidPrice
--> HouseListing listing
--> Person bidder
}
The composer-rest-server has generated an API with the following JSON string to post a transaction of type Offer:
{
"$class": "org.acme.purchasing.Offer",
"bidPrice": 0,
"listing": "string",
"bidder": "string",
"transactionId": "string",
"timestamp": "2017-07-21T13:37:09.460Z"
}
I've since replaced this with a sample transaction using the following JSON code derived from the above example:
{
"$class": "org.acme.purchasing.Offer",
"bidPrice": 1000,
"listing": "001",
"bidder": "RJOHNSON",
"transactionId": "1b9aa63c-dfad-4aad-a610-dfc80f2796b2",
"timestamp": "2017-07-21T13:37:09.460Z"
}
The response returned is error code 422:
{
"error": {
"statusCode": 422,
"name": "ValidationError",
"message": "The `Offer` instance is not valid. Details: `transactionId` can't be set (value: \"1b9aa63c-dfad-4aad-a610-d...6b2\").",
"details": {
"context": "Offer",
"codes": {
"transactionId": [
"absence"
]
},
"messages": {
"transactionId": [
"can't be set"
]
}
},
"stack": "ValidationError: The `Offer` instance is not valid. Details: `transactionId` can't be set (value: \"1b9aa63c-dfad-4aad-a610-d...6b2\").\n at /usr/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/dao.js:355:12\n at ModelConstructor.<anonymous> (/usr/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/validations.js:566:11)\n at ModelConstructor.next (/usr/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/hooks.js:93:12)\n at ModelConstructor.<anonymous> (/usr/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/validations.js:563:23)\n at ModelConstructor.trigger (/usr/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/hooks.js:83:12)\n at ModelConstructor.Validatable.isValid (/usr/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/validations.js:529:8)\n at /usr/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/dao.js:351:9\n at doNotify (/usr/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/observer.js:155:49)\n at doNotify (/usr/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/observer.js:155:49)\n at doNotify (/usr/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/observer.js:155:49)\n at doNotify (/usr/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/observer.js:155:49)\n at Function.ObserverMixin._notifyBaseObservers (/usr/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/observer.js:178:5)\n at Function.ObserverMixin.notifyObserversOf (/usr/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/observer.js:153:8)\n at Function.ObserverMixin._notifyBaseObservers (/usr/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/observer.js:176:15)\n at Function.ObserverMixin.notifyObserversOf (/usr/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/observer.js:153:8)\n at Function.ObserverMixin._notifyBaseObservers (/usr/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/observer.js:176:15)"
}
}
Now the strange thing is that I've deployed the same BNA onto the Hyperledger Composer Playground and am able to execute transactions of type Offer successfully.
Note that in the Playground, "transactionId" and "timestamp" are not specified as the Playground appears to take care of these values. For example, this is what Playground proposes to me initially:
{
"$class": "org.acme.purchasing.Offer",
"bidPrice": 0,
"listing": "resource:org.acme.purchasing.HouseListing#id:7965",
"bidder": "resource:org.acme.purchasing.Person#id:4441"
}
Can anyone advise why it's saying the Offer instance is not valid? My first thought was that it's not liking the string I'm placing in "transactionId" but another Stack Overflow post points out that the transactionId is just an arbitrary UUIDv4 string which I've generated already.
Update #1: Failing even with default demo
In order to ensure by BNA is error-free, I've deployed the default carauction-demo (resembles my example closely) onto my local Hyperledger Fabric instance and deployed the composer-rest-server. I've also deployed the same BNA into the Playground. All assets and participants were created identical in both from the Explorer (local instance) and Playground. When it comes time to submit an Offer transaction:
{
"$class": "org.acme.vehicle.auction.Offer",
"bidPrice": 800,
"listing": "resource:org.acme.vehicle.auction.VehicleListing#L001",
"member": "resource:org.acme.vehicle.auction.Member#member3#acme.org"
}
This JSON was generated by the Playground and succeeds there. Copy/paste/executing into the Explorer yields a status 500 error.
{
"error": {
"statusCode": 500,
"name": "Error",
"message": "error trying invoke chaincode. Error: chaincode error (status: 500, message: Error: Object with ID 'string' in collection with ID 'Asset:org.acme.vehicle.auction.VehicleListing' does not exist)",
"stack": "Error: error trying invoke chaincode. Error: chaincode error (status: 500, message: Error: Object with ID 'string' in collection with ID 'Asset:org.acme.vehicle.auction.VehicleListing' does not exist)\n at _initializeChannel.then.then.then.then.catch (/usr/lib/node_modules/composer-rest-server/node_modules/composer-connector-hlfv1/lib/hlfconnection.js:806:34)"
}
}
I'm still at a lost as to what is wrong here.
After much experimentation and some searching, I've concluded that the problem was that NPM was installed using sudo (as root). I redid the installation as non-root and the problem has now been solved. Everything is working as expected.
Composer updates the transactionId itself as its generated, you cannot do this in your JSON and hence why you get the error. This is a Loopback -> Swagger conversion issue as it should not appear in a /POST REST operation - captured here https://github.com/hyperledger/composer/issues/663
So I have successfully executed Offer transactions (/POST). I think the '500' error is because there is a missing field ('string' type), or relationship in your Offer transaction via REST.
Using the example of the Car Auction network https://github.com/hyperledger/composer-sample-networks/blob/master/packages/carauction-network/models/auction.cto
Either of these Offer transactions using /POST were successful in Explorer:
{
"$class": "org.acme.vehicle.auction.Offer",
"bidPrice": 20,
"listing": "org.acme.vehicle.auction.VehicleListing#100",
"member": "org.acme.vehicle.auction.Member#a#b.com"
}
OR
{
"$class": "org.acme.vehicle.auction.Offer",
"bidPrice": 20,
"listing": "org.acme.vehicle.auction.VehicleListing#100",
"member": "org.acme.vehicle.auction.Member#a#b.com",
"timestamp": "2017-07-28T14:07:02.558Z"
}
responded with a 200 (SUCCESS) and a transactionId in Explorer:
{
"$class": "org.acme.vehicle.auction.Offer",
"bidPrice": 20,
"listing": "org.acme.vehicle.auction.VehicleListing#100",
"member": "org.acme.vehicle.auction.Member#a#b.com",
"transactionId": "e75b9934-1f08-4daf-90db-702bbe4b8fa1"
}
This is my VehicleListing asset JSON for #100 above
{
"$class": "org.acme.vehicle.auction.VehicleListing",
"listingId": "100",
"reservePrice": 50,
"description": "string",
"state": "FOR_SALE",
"offers": [
{
"$class": "org.acme.vehicle.auction.Offer",
"bidPrice": 50,
"listing": "100",
"member": "resource:org.acme.vehicle.auction.Member#a#b.com",
"transactionId": "string123",
"timestamp": "2017-07-28T14:07:02.825Z"
}
],
"vehicle": "resource:org.acme.vehicle.auction.Vehicle#123"
}
And I created asset for Vehicle 123 as well as Member a#b.com
I am trying to make an AutoFillRequest using a SourceAndDestination object to describe the area to autofill. I've tested autofill requests using a GridRange object and everything works fine, but can't seem to get the SourceAndDestination working. Here is an example where I'm trying to autofill down the first row for 2 more rows.
HTTP POST
https://sheets.googleapis.com/v4/spreadsheets/{spreadsheetId}:batchUpdate
Request Body
{
"requests": [
{
"autoFill": {
"sourceAndDestination": {
"dimension": "ROWS",
"fillLength": 2,
"source": {
"sheetId": 1150108545,
"endRowIndex": 1,
"startRowIndex": 0
}
},
"useAlternateSeries": false
}
}
]
}
The response has an error code 400:
message = "Invalid requests[0].autoFill: No grid with id: 0" status =
"INVALID_ARGUMENT"
Sorry about that, this was a bug on the server. It's now fixed, so the above should work.