Deactivate buttons in Viber bot after click on it - javascript

I render buttons in Viber bot using rich_media message type and Viber REST API.
When user click on a button the buttons are still active and user can click on them once again. Here is an example of this behavior.
My source sode for rendering buttons:
var reply = {
type: "raw",
method: "send_message",
body: {
receiver: $request.data.chatId,
sender:{
name: "John McClane",
avatar: "http://avatar.example.com"
},
min_api_version: 2,
type: "rich_media",
rich_media: {
Type: "rich_media",
Buttons: [
{
Rows: 1,
ActionBody: "Option 1",
ActionType: "reply",
Text: "Option 1"
},
{
Rows: 1,
ActionBody: "Option 2",
ActionType: "reply",
Text: "Option 2"
},
{
Rows: 1,
ActionBody: "Option 3",
ActionType: "reply",
Text: "Option 3"
},
...
]
}
}
}
I need to make these buttons not active or remove from chat. How I can achive that?

Related

Iterate the data dynamically using Tiny Slider JS

I have array of objects that includes name and description. My goal here is to display the name and description dynamically in my image carousel with the help of Tiny Slider js.
I try the following attempt but failed.
Use .getElementById() to get the slider element and .map() to render the data inside the object but unfortunately the whole data was rendered in one slider only.
The actual result:
index.html
<div id="sliderCont" class="my-slider">
<div>
<div class="slide">
<div class="slide-img" style="background-image: url('src/images/img-1.jpg')">
View More
</div>
<br>
<div class="slide-info">
<h3 id="project-name"></h3>
<p id="project-description" class="subtext"></p>
</div>
</div>
</div>
</div>
app.js
const project = [
{
image: "",
name: "Project 1",
description: "Project Description here.",
},
{
image: "",
name: "Project 2",
description: "Project Description here. 2",
},
{
image: "",
name: "Project 3",
description: "Project Description here. 3",
},
{
image: "",
name: "Project 4",
description: "Project Description here. 4",
},
];
document.getElementById("project-name").innerHTML = project.map((proj) => proj.name);
document.getElementById("project-description").innerHTML = project.map((proj) => proj.description);
Tiny Slider Config
let slider = tns({
container: ".my-slider",
slideBy: 1,
speed: 200,
nav: false,
controlsContainer: "#controls",
prevButton: ".previous",
nextButton: ".next",
preventScrollOnTouch: "auto",
autoplay: true,
autoplayButtonOutput: false,
responsive: {
1600: {
items: 4,
gutter: 20,
},
1024: {
items: 3,
gutter: 20,
},
768: {
items: 2,
gutter: 20,
},
480: {
items: 1,
},
},
});
project.map((proj) => proj.name)
...returns an array:
["Project 1", "Project 2", "Project 3", "Project 4"]
When assigning this array to document.getElementById("project-name").innerHTML it is converted to the string "Project 1,Project 2,Project 3,Project 4".
So you're essentially assigning this string to the .project-name innerHTMLvalue:
document.getElementById("project-name").innerHTML = "Project 1,Project 2,Project 3,Project 4";
The same thing happens with:
document.getElementById("project-description").innerHTML = project.map(
(proj) => proj.description
);
Instead, first iterate, forEach(), over the project array, and in the loop block add a slide.
To create multiple slides use cloneNode() to copy the .slide DIV. (Since you're duplicating this DIV and it's child nodes, don't use IDs. Use class names instead: .project-name and .project-description.) And append the new node to the .slide's parentNode.
After the project array loop is exited, remove, removeChild(), the original .slide-info DIV.
const project = [
{
image: "https://source.unsplash.com/random?w=200",
url: "p1.html",
name: "Project 1",
description: "Project Description here."
},
{
image: "https://source.unsplash.com/random?w=200",
url: "p2.html",
name: "Project 2",
description: "Project Description here. 2"
},
{
image: "https://source.unsplash.com/random?w=200",
url: "p3.html",
name: "Project 3",
description: "Project Description here. 3"
},
{
image: "https://source.unsplash.com/random?w=200",
url: "p4.html",
name: "Project 4",
description: "Project Description here. 4"
},
];
// get target DIV, containing .slide-img, .project-url, .project-name, and .project-description
const slide = document.querySelector(".slide");
// iterate over project array
project.forEach(proj => {
// make a clone of .slide for new slide
const newslide = slide.cloneNode(true);
// add image background to .slide-img div
newslide.querySelector(".slide-img").style.backgroundImage = `url('${proj.image}')`;
// add url href to .project-url anchor tag
newslide.querySelector(".project-url").href = proj.url;
// add name to .project-name header
newslide.querySelector(".project-name").innerHTML = proj.name;
// add description to .project-description paragraph
newslide.querySelector(".project-description").innerHTML = proj.description;
// add slide to .slide parent
slide.parentNode.appendChild(newslide);
});
// remove original slide
slide.parentNode.removeChild(slide);
<div>
<div class="slide">
<div class="slide-img">
<a class="project-url" href="" style="color: white;">View More</a>
</div>
<br>
<div class="slide-info">
<h3 class="project-name"></h3>
<p class="project-description subtext"></p>
</div>
</div>
</div>

Displaying errors in slack modal view

I'm trying to create a modal which will enable the users to input a date for further use. This date cannot be a date from the past or present (only future dates). Slack indicates that it is possible to validate input data and display errors in the modal views here but I don't really understand this method (I'm a self-learner and a greenhorn).
here's my viewobject in the view.open:
{
type: "modal",
callback_id: "tests",
title: {
type: "plain_text",
text: "Tests",
emoji: true
},
submit: {
type: "plain_text",
text: "Send",
emoji: true
},
close: {
type: "plain_text",
text: "Cancel",
emoji: true
},
blocks: [
{
type: "input",
block_id: "datepicker",
optional: false,
element: {
action_id: "calendar",
type: "datepicker",
initial_date: "2020-09-05",
placeholder: {
type: "plain_text",
text: "Select a date",
emoji: true
}
},
label: {
type: "plain_text",
text: "Label",
emoji: true
}
}
]
}
I need help with displaying the error in the view ( I can already describe that error) after receiving view_submission. Thanks in advance!
First, I highly recommend that, in your code, you change the block_id from "datepicker" to something more descriptive. Slack's example uses "ticket-due-date", so I'll use that.
When a date is entered, Slack will send an HTTP POST request to the endpoint you specified in the Interactivity Request URL. That payload will look something like this (acquired from Block Kit Builder):
{
"type": "block_actions",
"user": {
"id": "U0CA5",
"username": "Amy McGee",
"name": "Amy McGee",
"team_id": "T3MDE"
},
"api_app_id": "A0CA5",
"token": "Shh_its_a_seekrit",
"container": {
"type": "message",
"text": "The contents of the original message where the action originated"
},
"trigger_id": "12466734323.1395872398",
"team": {
"id": "T0CAG",
"domain": "acme-creamery"
},
"response_url": "https://www.postresponsestome.com/T123567/1509734234",
"actions": [
{
"type": "datepicker",
"block_id": "ticket-due-date",
"action_id": "vxw",
"selected_date": "1990-04-26",
"initial_date": "1990-04-28",
"action_ts": "1599429672.233568"
}
]
}
When you receive that request, you need to validate actions[0].selected_date. If invalid, then send the payload below as a POST request to response_url.
{
"response_action": "errors",
"errors": {
"ticket-due-date": "You may not select a due date in the past"
}
}
You need to respond to the same request that is calling your endpoint.
Here's how the interaction endpoint would look like:
app.post("/your_endpoint", (req, res) => {
const validationErrors = {
datepicker: "Please enter a valid date"
};
// Respond to the request with an error payload
res.send({
response_action: "errors",
errors: validationErrors,
});
});

Kendo grid removes row, but does not call destory URL

I have a Kendo grid where I'm trying to add a delete feature. My datasource looks like:
var datasource = new kendo.data.DataSource({
transport: {
read: {
url: Router.action("Admin", "GetScansForMailItem", { mailItemIdnt: detailinit.data.MailItemIdnt }),
dataType: "json"
},
destroy: {
url: Router.action("Admin", "DeleteScan"),
type: "post"
}
},
model: {
id: "ScanIdnt",
fields: {
ScanIdnt: {editable: false, nullable: false}
}
},
pageSize: 5
});
I added the model part because this answer, however it made no difference.
The actual grid looks like:
.kendoGrid({
dataSource: datasource
scrollable: false,
sortable: true,
pageable: true,
editable: "inline",
columns: [{
field: "ScanIdnt",
title: "Scan ID"
}, {
field: "CreatedDate",
title: "Created",
template: "#= kendo.parseDate(CreatedDate, 'yyyy/MM/dd') #"
}, {
field: "ScanDocumentRelativePath",
title: "File Path",
template: "<a href='/CAMP/Admin/Download?scanIdnt=#= ScanIdnt #'>#= ScanDocumentRelativePath.substring(1) #</a>"
}, {
field: "ScanUserIdnt",
title: "Scanned By"
},{
command: "destroy",
title: ""
}]
});
Strangely, clicking the delete button removes the from the gird on the UI, but there is absolutely no Ajax call is made the the destroy URL. I can't seem to figure out why. Any ideas?
EDIT I'd like to point out that this grid is in fact a nested grid inside of another grid (like here) I discovered that the parent grid handles actually makes a call, but to the wrong function. For some reason, it clicking delete on a to level item calls the read function of the nested grid, however, the nested grids do nothing
Figured it out (sorta). While I think there were many issues with my code and the grid, It seems that when it came down to it, Kendo didn't like how I had my data.
In the Kendo docs related to hierarchical grids, the data for the child grid is stored in a field of the data for the parent. For example, given the following JSON:
"ParentItems": [
{
"Id": 12345 ,
"Name": "Test1",
"ChildItems": [
{"Id": 1, "Name": "Test"},
{"Id": 2, "Name": "Test"}
]
},
{
"Id": 12346 ,
"Name": "Test2",
"ChildItems": [
{"Id": 1, "Name": "Test"},
{"Id": 2, "Name": "Test"}
]
}
]
In the parent grid, each ParentItem would display it's respective ChildItems in the child grid.
On the other hand, I was pulling both data sets separately. Basically, I pulled the ParentItems like:
"ParentItems": [
{
"Id": 12345,
"Name" : "Test1"
},
{
"Id": 12346,
"Name" : "Test2"
}
]
And then made a second request to pull the child items, based on the parent's id.
"ChildItems": [
{"Id": 1, "Name": "Test", "ParentId": "12345"},
{"Id": 2, "Name": "Test", "ParentId": "12345"}
]
I was able to modify the server side code to serve the data like in the very first example and managed to get things working. The specific document that helped me out can be found here

hiding the Inactive Items form the Suggestions in kendo Multiselect

I have a multiselect in our application. I have a requirement where we should not show the Inactive users in the multi-select dropdown suggestions list. We have the flag in the model. So need to know we can filter the dropdown using that flag. Please find the attached screenshot to get the Idea.
We can filter the data in the ajax call using that flag. But need to get the Names of the already selected Inactive users. So I am trying to hide the Inactive users from the suggestions list only.
So need to show the selected Inactive users, but from the suggestions need to hide inactive users.
Not sure if this is the best way, but you can try applying a filter on the dataSource in open event and removing it in close event:
$("#multiselect").kendoMultiSelect({
dataSource: {
data: [{Name: "test 1", Active: true, Id: 1},
{Name: "test 2", Active: true, Id: 2},
{Name: "test 3", Active: false, Id: 3},
{Name: "test 4", Active: true, Id: 4},
{Name: "test 5", Active: false, Id: 5}]
},
value: [1, 3],
dataTextField: "Name",
dataValueField: "Id",
filter: "startswith",
open: function(e) {
this.dataSource.filter({ field: "Active", operator: "eq", value: "true" });
},
close: function() {
this.dataSource.filter(null);
}
});
Demo

Dynatree- Get Div ID

I have 2 same dynatrees in the same page as shown in this js fiddle http://jsfiddle.net/37ppf/3/.
$("#tree1").dynatree({
onSelect : function(select,node){},
checkbox: true,
children: [
{title: "Item 1",key:"1"},
{title: "Folder 2", isFolder: true, key:"2",
children: [
{title: "Sub-item 2.1", },
{title: "Sub-item 2.2", }
]
},
{title: "Item 3",key:"5"}
]
});
$("#tree2").dynatree({
onSelect : function(select,node){},
checkbox: true,
children: [
{title: "Item 1",key:"1"},
{title: "Folder 2", isFolder: true, key:"2",
children: [
{title: "Sub-item 2.1", },
{title: "Sub-item 2.2", }
]
},
{title: "Item 3",key:"5"}
]
});
<div id="tree1"> </div>
<div id="tree2"> </div>
Now When a user selects any node in any of the dynatree I want to get the div id in which the tree from which the user has selected the node is loaded.i.e if user selects from first tree I want to get output as tree1(div id) and if a node is selected from second tree i want to get tree2. Is this possible. I tried
$(this).closest(".dynatree-container").parent("div").attr("id")
But its coming undefined.
It feels super hacky, but you can do it this way:
onSelect : function(select,node){
alert(node.tree.$tree[0].id);
},
node.tree.$tree[0] will return the javascript object of its parent tree.
See the working code at
JSFiddle
Try this
$(document).on('click','span',function(){
console.log($(this).parents('div').attr('id'))
})
DEMO

Categories

Resources