How do I use a Link Addition (hyperlink) in Apple News Format without using markdown? - ios

I know that it is possible to include a hyperlink in an Apple News Format article using markdown by doing the following:
{
"version": "1.0",
"identifier": "sketchyTech_Demo",
"title": "My First Article",
"language": "en",
"layout": {},
"components": [
{
"role": "title",
"text": "My First Article",
"textStyle": "titleStyle"
},
{
"role": "body",
"format": "markdown",
"text": "Here's a [hyperlink](http://sketchytech.blogspot.co.uk).",
"textStyle": "bodyStyle"
}
],
"componentTextStyles": {
"titleStyle": {
"textAlignment": "center",
"fontName": "HelveticaNeue-Bold",
"fontSize": 64,
"lineHeight": 74,
"textColor": "#000"
},
"bodyStyle": {
"textAlignment": "left",
"fontName": "Georgia",
"fontSize": 18,
"lineHeight": 26,
"textColor": "#000"
}
}
}
but in Apple News Format there is also a Link Addition type, which I presume should work in a similar way to inline text styles, which are placed inside a component like this:
{
"role": "title",
"text": "My First Article",
"textStyle": "titleStyle",
"inlineTextStyles": [{
"rangeStart": 3,
"rangeLength": 5,
"textStyle": {
"textColor": "#FF00007F"
}
}
}
Apple provides sample code:
{
"type": "link",
"URL": "http://www.apple.com",
"rangeStart": 0,
"rangeLength": 20
}
But it doesn't give any instructions on where it should be placed like the other elements do. It is also rather mysterious that it has a "type" key, which is unlike other elements. Not only this but in the type description it is described as a LinkAddition in all uppercase. I have tried various combinations, the most obvious of which I would guess to be
"linkAdditions": [{
"type": "link",
"URL": "http://www.apple.com",
"rangeStart": 0,
"rangeLength": 20
}]
added to a component in the same way as inlineTextStyles (because a block of text could have multiple links, just as it can have multiple styles) but I can't get this or any variants that I've tried to work. Is it perhaps that News Preview isn't yet capable of rendering this?

Add it under the "additions" property instead of under "linkAdditions" inside of the component as you expected.
For example, this should work:
...
"role": "body",
"text": "Article text goes here and here",
"additions": [{
"type": "link",
"URL": "http://www.apple.com",
"rangeStart": 0,
"rangeLength": 20
}],
...
Note: if the format is markdown it will ignore the additions property.

Related

How to create zoom like response in slack bot message using block kit?

I have used zoom integration with slack. When I send /zoom command the bot responds with a new meeting link in a box layout that looks really good.
Note the bordered box below "Call"
However I am not able to create similar box layout with border and section in my own slack bot. Which block kit syntax should I use to achieve the same design?
At max what I am able to achieve is like the below:
I did not find any relevant example in the documentation as well.
There are multiple ways suggested in slack's official documentation to format Messages in responses.
For instance:
{
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "Hello, Assistant to the Regional Manager Dwight! *Michael Scott* wants to know where you'd like to take the Paper Company investors to dinner tonight.\n\n *Please select a restaurant:*"
}
},
{
"type": "divider"
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*Farmhouse Thai Cuisine*\n:star::star::star::star: 1528 reviews\n They do have some vegan options, like the roti and curry, plus they have a ton of salad stuff and noodles can be ordered without meat!! They have something for everyone here"
},
"accessory": {
"type": "image",
"image_url": "https://s3-media3.fl.yelpcdn.com/bphoto/c7ed05m9lC2EmA3Aruue7A/o.jpg",
"alt_text": "alt text for image"
}
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*Kin Khao*\n:star::star::star::star: 1638 reviews\n The sticky rice also goes wonderfully with the caramelized pork belly, which is absolutely melt-in-your-mouth and so soft."
},
"accessory": {
"type": "image",
"image_url": "https://s3-media2.fl.yelpcdn.com/bphoto/korel-1YjNtFtJlMTaC26A/o.jpg",
"alt_text": "alt text for image"
}
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*Ler Ros*\n:star::star::star::star: 2082 reviews\n I would really recommend the Yum Koh Moo Yang - Spicy lime dressing and roasted quick marinated pork shoulder, basil leaves, chili & rice powder."
},
"accessory": {
"type": "image",
"image_url": "https://s3-media2.fl.yelpcdn.com/bphoto/DawwNigKJ2ckPeDeDM7jAg/o.jpg",
"alt_text": "alt text for image"
}
},
{
"type": "divider"
},
{
"type": "actions",
"elements": [
{
"type": "button",
"text": {
"type": "plain_text",
"text": "Farmhouse",
"emoji": true
},
"value": "click_me_123"
},
{
"type": "button",
"text": {
"type": "plain_text",
"text": "Kin Khao",
"emoji": true
},
"value": "click_me_123",
"url": "https://google.com"
},
{
"type": "button",
"text": {
"type": "plain_text",
"text": "Ler Ros",
"emoji": true
},
"value": "click_me_123",
"url": "https://google.com"
}
]
}
]}
You can use these components to design your own experience in response.
Further reading: https://api.slack.com/messaging/composing
I think the elements you are referring to are produced by the Call API
It doesn't seem that it is an available block for use in message building.

Slack API invalid_block

I'm building a simple slack bot and I am playing with the checkboxes element.
When I return the following from my API in a JSON response to a slash-command I get an error failed with the error "invalid_blocks", however, when I put this in the block-kit-builder it works perfectly (including "sending to slack" button)
Any ideas why this is failing when I run my slash command - and is it possible to see more detailed error messages from slack?
{
"blocks": [
{
"elements": [
{
"style": "primary",
"text": {
"emoji": true,
"text": "Create new TODO list",
"type": "plain_text"
},
"type": "button",
"value": "value"
},
{
"style": "primary",
"text": {
"emoji": true,
"text": "Help",
"type": "plain_text"
},
"type": "button",
"value": "value"
}
],
"type": "actions"
},
{
"text": {
"text": "Today",
"type": "mrkdwn"
},
"type": "section"
},
{
"elements": [
{
"initial_options": [
{
"text": {
"text": "Get Into the garden",
"type": "mrkdwn"
},
"value": "foo"
}
],
"options": [
{
"text": {
"text": "Get Into the garden",
"type": "mrkdwn"
},
"value": "foo"
}
],
"type": "checkboxes"
},
{
"style": "primary",
"text": {
"emoji": true,
"text": "Add new Task",
"type": "plain_text"
},
"type": "button",
"value": "value"
}
],
"type": "actions"
}
],
"type": "home"
}
I am using the Slack Web API. I was getting the similar error. After a lot of looking around, here's how I solved it.
import json
blocks = [{...}]
payload = {
"blocks": json.dumps(blocks)
}
You will then send this payload.
in the api, the "blocks" parameter need to be string type. Did you convert it to string or you use it as a JSON ?
https://api.slack.com/methods/chat.postMessage
In the Block Kit Builder, the data is a JSON with a blocks key.
In the Slack API, the blocks param is only the list of JSON objects.
blocks = [
{
"text": {
"text": "Its the list of your blocks",
"type": "mrkdwn"
},
"type": "section"
}
]
text = 'Alternative data in text'
client.chat_postMessage(channel=channel_id, blocks=blocks, text=text)
Another cause of this problem seems to be too many blocks being returned. I can't find any documentation about this whatsoever, but personal experience seems to indicate about 20 blocks is the maximum.
An alternative is to return fewer blocks, with paging actions -- paging works well with the "replace" message so that the content being paged through does not result in many separate messages.
It appears that not all valid elements in block kit tool can be posted as a message, despite the fact that message preview works fine in the Block Tool.
In my case, the code failed when I included an input block and passed when i removed it. The input block was generated by the Block Kit tool.
{
"type": "input",
"element": {
"type": "plain_text_input",
"action_id": "plain_text_input-action"
},
"label": {
"type": "plain_text",
"text": "Feedback",
"emoji": true
}
}
The error was
{'ok': False, 'error': 'invalid_blocks'}
Also, although the documentation for python says you need to urlEncode the JSON-based array, there is no example, and it is incorrect. https://api.slack.com/methods/chat.postMessage
You can see on line 29 in the SDK test code below that blocks= takes a regular list of dicts not a string.
https://github.com/slackapi/python-slack-sdk/blob/c9dc6aa0907a72c16cf36aa15e7e80031a9fdce2/integration_tests/samples/basic_usage/sending_a_message.py

back button with jasonett/iOS

I am trying to create a back button that when the user clicks on it, it will take them to the previous page.
I found this code of a medium post by the author of Jasonett but it doesn't work for me. It creates the label but I can't click on it
"layers": [{
"type": "label",
"text": "👈",
"style": {
"top": "10",
"right": "10",
"width": "100",
"height": "100"
},
"action": {
"type": "$back"
}
}]
Source: The documentation
The element label is clickable or you can attach an action on a label only if it is at the item level.
So, for example, the following code will accept touch and the action set there would work fine.
{
"items": [{
"type": "label",
"text": "Submit",
"action": { SOME_ACTION }
}]
}
Where as the following won't accept a click.
{
"items": [{
"type": "vertical",
"components": [{
"type": "label",
"text": "touch me",
"action": { ... }
}]
}]
}
In your example, label is defined inside layers. Thus it is not accepting a click.
Basically you have two options here.
Implement a click handler in JasonLabelComponent.m so regardless of their position labels always respond to action if it is provided in JSON.
Take the label out and make it a button, which by default would have action enabled.

SurveyMonkey: Where is the text of my respondent's response?

I'm new to the SurveyMonkey API and it hasn't been too difficult to get payloads back from API calls, but right now I'm trying to get back what responses a specific respondent gave.
I have a survey which has two respondents, the first question on the survey asks the user to enter three pieces of information: Their Name, an ID and today's date.
So, if I do a call to get_survey_details, I can see the questions just fine. For example
obj.pages[0].questions[0].answers[0].answerid: "xxxxxxxx" //some long ID
obj.pages[0].questions[0].answers[0].text: "Enter Your Name"
obj.pages[0].questions[0].answers[0].type: "row"
There's a couple more pieces of information in that object, like whether the question is visible, etc., but these seem to be the pertinent pieces to the question I have.
So! I make another call to get_responses using the same survey_id and respondent_id (there's only two so actually I get them both).
In the resulting payload I get an array of 2 objects (one to hold each respondents responses). So I look in the first (obj[0]) and I see an array of questions and the respondent id. Fine. I look in the questions array and I see one object for each question and in each of those an answers object.
so that's:
obj[0].questions[0].answers[0].col: "yyyyyy" //some long ID
obj[0].questions[0].answers[0].row: "nnnnnn" //some other long ID
No response text. just this row/col business.
At this point, I'm super-confused (which is like regular confused, but with a cape). Where the heck are the respondents actual responses?
What the heck does "row" and "column" reference? Do I have to do some other API call with the row and/or column in order to get the text of the respondent's response?
I've looked through the documentation (and will continue to do so after posting this) and through stackoverflow to see if anyone else has asked this before. There was one question that came close, but really they were just forgetting to pair 'get_responses' with 'get_survey_details'. I'm doing that, but am still lost as ever. And I don't see any documentation really explaining in detail how this row/column concept works for mapping responses to the text of the response. :/
I know this is a really long-winded question, but I'm just so confused as to how to actually get responses out of this API. :(
Thanks for reading.
The text for a given response should come through under the "text" key. e.g. for a survey that only consists of an essay style question:
{
"status": 0,
"data": [
{
"respondent_id": "123456",
"questions": [
{
"answers": [
{
"text": "This is an essay style answer.",
"row": "0"
}
],
"question_id": "78910"
}
]
}
]
}
"row" and "col" literally reference the row and column of an answer - e.g. in a matrix question, there will be a list of rows for different questions ("what did you think of the hotel?") and ratings ("bad, okay, great") - and each answer is a combination of these. For a regular multiple choice question there will be multiple rows and only one column.
Calling "get_responses" with the correct respondent_id should provide you with the text response that you want. It's only the fixed details of the answer stored in the survey itself you should have to look up (provided in get_survey_details).
Using GET : /surveys/{survey_id}/details, we can get the corresponding question Ids along with the answer Ids.
{
"pages": [
{
"href": "https://api.surveymonkey.net/v3/surveys/87263608/pages/260492760",
"description": "",
"questions": [
{
"sorting": null,
"family": "matrix",
"subtype": "rating",
"required": {
"text": "This question requires an answer.",
"amount": "0",
"type": "all"
},
"answers": {
"rows": [
{
"visible": true,
"text": "",
"position": 1,
"id": "10788526669"
}
],
"choices": [
{
"description": "Not at all likely",
"weight": -100,
"id": "10788526670",
"visible": true,
"is_na": false,
"text": "Not at all likely - 0",
"position": 1
},
{
"description": "",
"weight": -100,
"id": "10788526671",
"visible": true,
"is_na": false,
"text": "1",
"position": 2
},
{
"description": "",
"weight": -100,
"id": "10788526672",
"visible": true,
"is_na": false,
"text": "2",
"position": 3
},
{
"description": "",
"weight": -100,
"id": "10788526673",
"visible": true,
"is_na": false,
"text": "3",
"position": 4
},
{
"description": "",
"weight": -100,
"id": "10788526674",
"visible": true,
"is_na": false,
"text": "4",
"position": 5
},
{
"description": "",
"weight": -100,
"id": "10788526675",
"visible": true,
"is_na": false,
"text": "5",
"position": 6
},
{
"description": "",
"weight": -100,
"id": "10788526676",
"visible": true,
"is_na": false,
"text": "6",
"position": 7
},
{
"description": "",
"weight": 0,
"id": "10788526677",
"visible": true,
"is_na": false,
"text": "7",
"position": 8
},
{
"description": "",
"weight": 0,
"id": "10788526678",
"visible": true,
"is_na": false,
"text": "8",
"position": 9
},
{
"description": "",
"weight": 100,
"id": "10788526679",
"visible": true,
"is_na": false,
"text": "9",
"position": 10
},
{
"description": "Extremely likely",
"weight": 100,
"id": "10788526680",
"visible": true,
"is_na": false,
"text": "Extremely likely - 10",
"position": 11
}
]
},
"visible": true,
"href": "https://api.surveymonkey.net/v3/surveys/87263608/pages/260492760/questions/1044924866",
"headings": [
{
"heading": "How likely is it that you would recommend XYZ to a friend or colleague?"
}
],
"position": 1,
"validation": null,
"id": "1044924866",
"forced_ranking": false
},
{
"sorting": null,
"family": "single_choice",
"subtype": "vertical",
"required": null,
"answers": {
"choices": [
{
"visible": true,
"text": "High Interest",
"position": 1,
"id": "10788529403"
},
{
"visible": true,
"text": "Long process",
"position": 2,
"id": "10788529404"
},
{
"visible": true,
"text": "Low XYZ Amount",
"position": 3,
"id": "10788529405"
},
{
"visible": true,
"text": "Lot of Documents",
"position": 4,
"id": "10788529406"
},
{
"visible": true,
"text": "Bad customer service",
"position": 5,
"id": "10788529407"
}
]
},
"visible": true,
"href": "https://api.surveymonkey.net/v3/surveys/87263608/pages/260492760/questions/1044925207",
"headings": [
{
"heading": "What is the most important issue which we need to address for overall a better service?"
}
],
"position": 2,
"validation": null,
"id": "1044925207",
"forced_ranking": false
}
],
"title": "",
"position": 1,
"id": "260492760",
"question_count": 2
}
],
}
We can use these ids to decipher the answer we get after fetching responses using get response API(Bulk or each respondent).
For eg:,
If my survey has two questions, like
Then after fetching the responses we get a json like this:
{
"total_time": 34,
"href": "https://api.surveymonkey.net/v3/collectors/94630092/responses/5120000552",
"custom_variables": {},
"ip_address": "182.76.20.30",
"id": "5120000552",
"logic_path": {},
"date_modified": "2016-12-01T11:01:11+00:00",
"response_status": "completed",
"custom_value": "LAI100023",
"analyze_url": "http://www.surveymonkey.com/analyze/browse/EvaBWWcU9K1XTH_2FFFBTfFul4ge94MwVWvBk0eAFDJ3c_3D?respondent_id=5120000552",
"pages": [
{
"id": "260492760",
"questions": [
{
"id": "1044924866",
"answers": [
{
"choice_id": "10788526677",
"row_id": "10788526669"
}
]
},
{
"id": "1044925207",
"answers": [
{
"choice_id": "10788529404"
}
]
}
]
}
],
"page_path": [],
"recipient_id": "2743199128",
"collector_id": "94630092",
"date_created": "2016-12-01T11:00:37+00:00",
"survey_id": "87263608",
"collection_mode": "default",
"edit_url": "http://www.surveymonkey.com/r/?sm=SfTljxZSoBFvaRUeGSI6L813qctjfG_2FDCVcqCks7CDc4TcJC_2BNHqmPYD7NNTcvST",
"metadata": {
"contact": {
"first_name": {
"type": "string",
"value": "John"
},
"last_name": {
"type": "string",
"value": "Doe"
},
"email": {
"type": "string",
"value": "neeta#xyz.com"
}
}
}
}
We can map the questions and answers using their IDs in this response with the ids we got from survey details. For open ended text questions, we get direct typed responses.

Is is Possible to have nested Context Menus in Sublime Text 2/3?

Sublime Text's Context menu has a few default items like Copy,Cut,paste, Select all etc... I know that we can add/remove items via configuration but can we have nested menus(menus within menus) like the one we have in chrome or notepad++.
I may not fully understand your question, we surely can customize our context menu with nested menus(menus within menus), all we need to do is creating a "Context.sublime-menu" file under "Packages\User" folder, make create customized menu items like this:
[
{
"caption": "-",
"id": "separator"
},
{
"caption": "First Level Menu",
// "mnemonic": "f",
"id": "firstlevelmenu",
"children":
[
{
"command": "Command1",
"caption": "command1"
},
{
"command": "Command2",
"caption": "command2"
},
{
"caption": "Second Level Menu",
"children":
[
{
"command": "Command3",
"caption": "command3"
},
{
"command": "Command4",
"caption": "command4"
}
]
},
]
},
{
"caption": "-",
"id": "separator"
}
]
Keyword "children" is the one to create sub-menus.
Hope it helps.

Resources