According to the smartsheet API Docs, I should be able to use "level" parameter in my options to get a complex object for Multi-Contact columns.
Unfortunately all I'm getting in return is value and displayValue.
Am I doing something wrong here?
var options = {
id: SHEET_ID, //Id of sheet
queryParameters = {
include: ["objectValue"],
level: 1
}
}
ss.sheets.getSheet(options)
.then(function (results) {
console.log(results.rows[args[0]].cells[6])
})
The above code returns:
{ columnId: 8746190272522116, displayValue: 'John Smith, Danny Doe' }
I've verified (using Postman) that Smartsheet API does indeed support the scenario you've described. i.e., if I submit this Get Sheet request:
https://api.smartsheet.com/2.0/sheets/5831916227192708?include=objectValue&level=1
...then the response does include the complex object for a multi-contact cell in my sheet:
{
"id": 5831916227192708,
...
"rows": [
{
"id": 5942480978372484,
...
"cells": [
{
"columnId": 3992195570132868,
"objectValue": {
"objectType": "MULTI_CONTACT",
"values": [
{
"objectType": "CONTACT",
"email": "john_doe#test.com",
"name": "John Doe"
},
{
"objectType": "CONTACT",
"email": "jane_doe#test.com",
"name": "Jane Doe"
}
]
},
"displayValue": "John Doe, Jane Doe"
},
...
]
},
...
]
}
However, it looks like the Smartsheet JavaScript SDK doesn't yet support this scenario.
It's not unusual for SDK updates to lag a bit behind the release of new API features. You might consider logging an issue in the JavaScript SDK repo to request that support for this scenario be added -- or better yet, submit a PR to that repo that adds support for this scenario. In the meantime, you'll need to implement this functionality yourself within your integration (i.e., since you can't rely on the out-of-the-box SDK functionality to provide it at this time).
You just need to remove the array notations from your options definition:
var options = {
id: SHEET_ID, //Id of sheet
queryParameters = {
include: "objectValue",
level: 1
}
}
ss.sheets.getSheet(options)
.then(function (results) {
console.log(results.rows[args[0]].cells[6])
})
Related
I have two different collections for two different type of products. Now, I want to fetch all documents from both collections for a particular user.
I know I can do that with 2 queries for each collection, merging them on the server side and sending the result to the user. Downside of this is that I have to fetch all documents for a user from both collections, which is not good for pagination. That is why I want to do it in one query, so I can leave a pagination logic to MongoDB as well.
Here is the example of collections and expected result:
Products_type_1
[
{
"name": "product_1",
"user": "user_1",
...
},
{
"name": "product_2",
"user": "user_2",
...
}
]
Products_type_2
[
{
"name": "product_3",
"user": "user_1",
...
},
{
"name": "product_4",
"user": "user_2",
...
}
]
The expected result:
[
{
"type": "Products_type_1",
"name": "product_1",
"user": "user_1",
...
},
{
"type": "Products_type_2",
"name": "product_3",
"user": "user_1",
...
}
]
You can use aggregation framework with $unionWith stage:
db.Products_type_1.aggregate([
{
"$match": {
"user": "user_1"
}
},
{
$unionWith: {
coll: "Products_type_2",
pipeline: [
{
"$match": {
"user": "user_1"
}
}
]
}
}
])
Playground: https://mongoplayground.net/p/v0dKCwiKsZU
If you want to use pagination you will need to add sort stage to ensure consistent order of the documents in the result.
Firstly I would query the logic of having a different collection for the different 'product_type_x'. If you had a single collection with an added field...
{ "productType" : 1,
...
},
That way that issue has just been resolved, everything to do with Procts is now accessible in a single collection. Aggregation of your data now becomes simple (by comparison)
I have an Apollo Client that I'm using to request data from a service. I want to use the data I get in response to create a network of nodes and links e.g.
// Response data:
{
"Team": [
{
"name": "Example Team",
"members": [
{ "name": "Bob" },
{ "name": "Alice" }
]
}
]
}
// Network data:
{
"nodes": [
{ "name": "Example Team" }
{ "name": "Bob" },
{ "name": "Alice" }
],
"links": [
{ "source": "Example Team", "target": "Bob" },
{ "source": "Example Team", "target": "Alice" }
]
}
Historically, before using GraphQL, I would have used Redux to store the munged API response in state and read from there.
Is it appropriate to take a GraphQL result from Apollo and immediately save it back to Apollo local state in a different form so it can be queried by components in that format?
The main problem I foresee is that I think I'd have to query to check if the data I want exists in local state, then make another query if it didn't. In a Redux-world this would be wrapped up inside my store which would then only make the request off to the API if it didn't have the data it needed which 'feels' much cleaner.
In my case this could be solved using Afterware in Apollo Client, see this answer for more information.
It would allow me to munge the returned data into the form I need, and return it in the response alongside the original data.
I would like to get a modified response object. For example I dont know how to get the user object without the roles.
The default response is:
{
"id": 6,
"username": "username",
"email": "user#email.com",
"provider": "local",
"confirmed": true,
"blocked": false,
"role": {
"id": 2,
"name": "Authenticated",
"description": "Default role given to authenticated user.",
"type": "authenticated"
}
}
Now I want to get the same response without the role attribute.
{
"id": 6,
"username": "username",
"email": "user#email.com",
"provider": "local",
"confirmed": true,
"blocked": false
}
Currently you cannot do this in the Rest API unless you change the UserController provided by permissions plugin, which is not recommended.
What you can do then is to use the GraphQL plugin provided by Strapi, so you can query only the fields you need on client side.
The docs about how to use GraphQL plugin are here.
For anyone still struggling with this problem:
The latest versions of strapi do support custom queries, you can pass an array containing all the names of relations you wish to populate (only relations!).
If you don't want to populate any relationships, you can keep it empty, your controller would then look something like this:
module.exports = {
UserWithoutRoles: ctx => {
return strapi.query('user').findOne({ id: ctx.params.id }, ['']);
}
}
If you do wish to populate it, it would be like this:
module.exports = {
UserWithoutRoles: ctx => {
return strapi.query('user').findOne({ id: ctx.params.id }, ['role']);
}
}
Also see:
[https://strapi.io/documentation/3.0.0-beta.x/concepts/queries.html#api-reference][1]
I am using Apollo-Server and trying to create a REST query against the IEX REST API which returns back data that looks like this:
{
"symbol": "AAPL",
"companyName": "Apple Inc.",
"exchange": "Nasdaq Global Select",
"industry": "Computer Hardware",
"website": "http://www.apple.com",
"description": "Apple Inc is an American multinational technology company. It designs, manufactures, and markets mobile communication and media devices, personal computers, and portable digital music players.",
"CEO": "Timothy D. Cook",
"issueType": "cs",
"sector": "Technology",
"tags": [
"Technology",
"Consumer Electronics",
"Computer Hardware"
]
}
I am using datasources. My typeDefs and resolvers look something like this:
const typeDefs = gql`
type Query{
stock(symbol:String): Stock
}
type Stock {
companyName: String
exchange: String
industry: String
tags: String!
}
`;
const resolvers = {
Query:{
stock: async(root, {symbol}, {dataSources}) =>{
return dataSources.myApi.getSomeData(symbol)
}
}
};
The Datasource file looks like this:
class MyApiextends RESTDataSource{
constructor(){
super();
this.baseURL = 'https://api.iextrading.com/1.0';
}
async getSomeData(symbol){
return this.get(`/stock/${symbol}/company`)
}
}
module.exports = MyApi
I can run a query and get data back, but it is not formatting in an array and is throwing an error when I run a query like so:
query{
stock(symbol:"aapl"){
tags
}
}
Error:
{
"data": {
"stock": null
},
"errors": [
{
"message": "String cannot represent value: [\"Technology\", \"Consumer Electronics\", \"Computer Hardware\"]",
"locations": [
{
"line": 3,
"column": 5
}
],
"path": [
"stock",
"tags"
],
"extensions": {
"code": "INTERNAL_SERVER_ERROR",
"exception": {
"stacktrace": [
"TypeError: String cannot represent value: [\"Technology\", \"Consumer Electronics\", \"Computer Hardware\"]",
The data I am expecting (technology, consumer electronics, and computer hardware) are correct, but not returning in an array. I tried to make a new type for tags, and set the it with a tag property, but the value just returns null.
I am very new to graphql, so any feedback is appreciated!
Inside your type definition for Stock, you're defining the type for the tags field as String!:
tags: String!
That tells GraphQL to expect a String value that will not be null. The actual data being returned by the REST endpoint, however, is not a String -- it's an array of Strings. So your definition should minimally look like this:
tags: [String]
If you want GraphQL to throw if the tags value is null, add an exclamation point to the end to make it non-nullable:
tags: [String]!
If you want GraphQL to throw if any of the values inside the array are null, add an exclamation point inside the brackets. You can also combine the two:
tags: [String!]!
I'm trying to create Google classrooms from a spreadsheet using App Script. I can create the classes successfully, but it's not adding the course materials (1 Doc) to the about page.
This is the code I am using and I've tried using the API reference to no avail.
Can someone please advise me on how to correctly format the courseMaterialSets to include a Google Doc from my drive.
var create = Classroom.Courses.create({
"ownerId": '-My email address-',
"name": getData[i][0],
"section": getData[i][1],
"descriptionHeading": getData[i][2],
"description": getData[i][2],
"courseMaterialSets" : [{
"title" : 'Course Outline',
"materials" : [{
"driveFile" : {
"id" : getData[i][5],
"title" : 'Course Outline' ,
"alternateLink": getData[i][4],
"thumbnailUrl" : 'https://drive.google.com/uc?export=download&id=-Image ID-',
},
}
]
}
]
})
}
Logger.log(create)
}
Thank you.
EDIT
I've updated the code to reflect the suggestions in the comments and logged the value of var create which returns all of the info of the newly created Classroom but with no mention of the course material set.
According to the documentation you have to specify the DriveFile object with JSON.
"driveFile" : {
"id": theDocIdString,
"title": theDocTitleString,
"alternateLink": urlToFileString,
"thumbnailUrl": imgThumbnailString
}
You can of course pull all of this data from a sheet or use variables to loop through resources.
Here is the code I tried to successfully create a course, but I also do not get the course materials to attach to the ABOUT tab of the Google Classroom created.
function createCourse() {
var resource = {
name: "XYZ course",
room: "The Great Hall",
ownerId: "me",
courseMaterialSets: [{
title: "course materials",
materials: [
{
driveFile: {
id: "insert id of google drive file"
}
}
],
}],
}
var newCourse = Classroom.Courses.create(resource);
}
I also tried creating the course and then accepting the course in Google Classroom and the trying to add the classroom set. This also was not successful.
function addClassSet() {
var id = "course id obtained with sample script in documentation";
var resource = {
name: "XYZ course",
room: "The Great Hall",
courseMaterialSets: [{
title: "course materials",
materials: [
{
driveFile: {
id: "drive file id" //drive file was not added
}
}
],
}],
description: "This is a trial course", //this worked
}
Classroom.Courses.update(resource, id);
}
Is it because the documentation states that the courseMaterialsSets is Read only???