How to create outlook calendar event with custom value? - outlook

I want to create the outlook calendar event with custom value. Because i need to get some value while open the event.
Is this possible to send the custom value while creating the event in outlook add in - calendar event.
const msalConfig = {
auth: {
clientId: CLIENT_ID, // Client Id of the registered application
redirectUri: REDIRECT_URL,
},
};
const graphScopes = ["user.read", "mail.send", "openid", "profile"]; // An array of graph scopes
const msalApplication = new UserAgentApplication(msalConfig);
const options = new MSALAuthenticationProviderOptions(graphScopes);
const authProvider = new ImplicitMSALAuthenticationProvider(
msalApplication,
options
);
const option = {
authProvider, // An instance created from previous step
};
const client = Client.initWithMiddleware(option);
Example Event :
let event = {
"subject": "Let's go for lunch",
"body": {
"contentType": "HTML",
"content": "Does mid month work for you?"
},
"start": {
"dateTime": "2021-08-13T12:00:00",
"timeZone": "Pacific Standard Time"
},
"end": {
"dateTime": "2021-08-13T14:00:00",
"timeZone": "Pacific Standard Time"
},
"location":{
"displayName":"Harry's Bar"
},
"attendees": [
{
"emailAddress": {
"address":"adelev#contoso.onmicrosoft.com",
"name": "Adele Vance"
},
"type": "required"
}
]
};
client.api("/me/events").post(event, (err, res) => {
this.setState({ isLoading: false });
});
I want to pass the custom value while create the event. Is this possible to create the event with custom value.

You can use the Microsoft Graph API to create a Calendar event from custom data.

Related

C# Microsoft Bot Schema Teams Image cropping off the top and bottom

I had a question regarding Teams Microsoft Bot framework. Whenever my bot sends an adaptive card, the top and the bottom of the photo continue to cut off. Inside the adaptive card is the hero card image, it seems I'm unable to resize it to make it fit. I've tried making the image smaller and larger to see if that would fix the issue. Below is a screenshot of the issue I am having.
I'm hoping someone has run into the same issue and if this is fixable or not. Thank you.
Image being used; https://imgur.com/a/hkcSkrJ
public async Task<SendResult> SendAsync(NotificationTeamsAttempt attempt)
{
try
{
if (string.IsNullOrWhiteSpace(attempt.ConversationId))
throw new Exception("Conversation Id is required.");
if (string.IsNullOrWhiteSpace(attempt.ServiceUrl))
throw new Exception("Service Url is required.");
using (var connector = new ConnectorClient(new Uri(attempt.ServiceUrl), _clientId, _clientSecret))
{
var activity = MessageFactory.Text("");
activity.Attachments.Add(attempt.Attachment());
activity.Summary = attempt.Summary();
var response = await connector.Conversations.SendToConversationAsync(attempt.ConversationId, activity);
return new SendResult
{
IsSuccess = true,
DispatchId = response.Id
};
}
}
catch (Exception exception)
{
return new SendResult
{
IsSuccess = false,
Exception = exception
};
}
}
public override Attachment Attachment()
{
var card = new ThumbnailCard
{
Title = "Post submitted for review by " + DraftAuthor,
Subtitle = DraftTitle,
Text = DraftDescription,
Images = new List<CardImage>(),
Buttons = new List<CardAction>()
};
if (!string.IsNullOrWhiteSpace(TeamsUrl))
{
card.Buttons.Add(new CardAction
{
Type = "openUrl",
Title = "Review in Teams",
Value = TeamsUrl.Replace("null", $"%22post%7C{DraftId}%7C{DraftId}%22")
});
}
if (!string.IsNullOrWhiteSpace(SPUrl))
{
card.Buttons.Add(new CardAction
{
Type = "openUrl",
Title = "Review in SharePoint",
Value = $"{SPUrl}?postId={DraftId}&sourceId={DraftId}"
});
}
return card.ToAttachment();
}
Please disregard the black lines I've added. But below you can see where the image is cropping off.
Image of the cropping.
Moving comment to answer -
We are using the below JSON and we get the perfect image without cropping -- { "type": "AdaptiveCard", "body": [ { "type": "TextBlock", "size": "Medium", "weight": "Bolder", "text": "card image test" }, { "type": "Container", "items": [ { "title": "Public test 1", "type": "Image", "url": "https://i.imgur.com/OiJNN03.jpeg" } ] } ], "$schema": "adaptivecards.io/schemas/adaptive-card.json", "version": "1.0" }

Slack Bolt App: Options body view state is not updated like actions body view state

I am trying to implement dependent external selects inside a modal but I am having problems passing the state of the first dropdown to the second. I can see the state I need inside the app.action listener but I am not getting the same state inside the app.options listener.
body.view.state inside app.action("case_types"). I specifically need the case_create_case_type_block state.
"state": {
"values": {
"case_create_user_select_block": {
"case_create_selected_user": {
"type": "users_select",
"selected_user": "U01R3AE65GE"
}
},
"case_create_case_type_block": {
"case_types": {
"type": "external_select",
"selected_option": {
"text": { "type": "plain_text", "text": "Incident", "emoji": true },
"value": "Incident"
}
}
},
"case_create_case_subtype_block": {
"case_subtypes": { "type": "external_select", "selected_option": null }
},
"case_create_case_owner_block": {
"case_owners": { "type": "external_select", "selected_option": null }
},
"case_create_subject_block": {
"case_create_case_subject": {
"type": "plain_text_input",
"value": null
}
},
"case_create_description_block": {
"case_create_case_description": {
"type": "plain_text_input",
"value": null
}
}
}
},
body.view.state inside app.options("case_subtypes")
"state": {
"values": {
"case_create_user_select_block": {
"case_create_selected_user": {
"type": "users_select",
"selected_user": "U01R3AE65GE"
}
}
}
},
I did also try to update the view myself hoping it would update the state variables inside app.action({ action_id: "case_types" })
//need to update view with new values
try {
// Call views.update with the built-in client
const result = await client.views.update({
// Pass the view_id
view_id: body.view.id,
// Pass the current hash to avoid race conditions
hash: body.view.hash,
});
console.log("Case Type View Update result:");
console.log(JSON.stringify(result));
//await ack();
} catch (error) {
console.error(error);
//await ack();
}
I ended up posting this on the github issues page for slack bolt. This was a bug that will fixed in a future release. Below is the workaround using private metadata to hold the state to check for future dependent dropdowns.
// Action handler for case type
app.action('case_type_action_id', async ({ ack, body, client }) => {
try {
// Create a copy of the modal view template and update the private metadata
// with the selected case type from the first external select
const viewTemplate = JSON.parse(JSON.stringify(modalViewTemplate))
viewTemplate.private_metadata = JSON.stringify({
case_type: body.view.state.values['case_type_block_id']['case_type_action_id'].selected_option.value,
});
// Call views.update with the built-in client
const result = await client.views.update({
// Pass the view_id
view_id: body.view.id,
// Pass the current hash to avoid race conditions
hash: body.view.hash,
// Pass the updated view
view: viewTemplate,
});
console.log(JSON.stringify(result, 0, 2));
} catch (error) {
console.error(error);
}
await ack();
});
// Options handler for case subtype
app.options('case_subtype_action_id', async ({ body, options, ack }) => {
try {
// Get the private metadata that stores the selected case type
const privateMetadata = JSON.parse(body.view.private_metadata);
// Continue to render the case subtype options based on the case type
// ...
} catch (error) {
console.error(error);
}
});
See the full explaination here: https://github.com/slackapi/bolt-js/issues/1146

is there a way to choose which object to return based on it's attribute in vuex?

I have an array of objects named Employees and am trying to get the ones who are department_id=3 and I don't want to go back to laravel and make another request so is there a way to do so with vuex?
"id": 25,
"name": "name",
"email": "name#gmail.com",
"last_name": "lastname",
"phone": "98745632",
"gender": "Male",
"nationality": "Tunisian",
"school": "ISIMM",
"experience_level": "2",
"source": "Linkedin",
"hiring_date": "2020-04-17",
"end_contract": "2020-04-18",
"position": "web developer",
"grade": "Junior",
"contract": "Cdi",
"department_id": 1,
"company_id": 1,
"archived": "0",
"img": null,
"supervisor_id": 1,
"ipAdress": null,
"last_login_at": null,
"department": {
"id": 1,
"name": "mobile"
},
here's
state :
const employee = {
state: {
Employees: [],
sysAdmins: [],
},
here's
getters :
sysAdmins: (state) =>
state.Employees.map((element) => (element.department_id = "3")),
Employees: (state) => state.Employees,
here's
mutations :
getsysAdmins(state, employees) {
state.sysAdmins = employees;
},
getEmployees(state, employees) {
state.Employees = employees;
},
here's
actions :
getEmployees(context) {
const config = {
headers: {
"x-api-key": process.env.VUE_APP_SIRH_X_API_KEY,
Authorization: localStorage.getItem("access_token"),
},
};
return new Promise((resolve, reject) => {
axios
.get("/employees/all_employees", config)
.then((response) => {
context.commit("getEmployees", response.data.data.users);
context.commit("getsysAdmins", response.data.data.users);
resolve(response);
})
.catch((error) => {
reject(error);
});
});
},
If I understand it right, you want to return the while Employee Object for those employees that work in a certain department.
You can do this by filtering your Employees array. I would write that as following:
getters: {
employees: (state) => state.Employees,
sysAdmins: (state) => state.Employees.filter((employee) => employee.department_id === 3),
// If your DB returns a string as the department_id, you'll have to check against "3"
}
If sysAdmins is always a subset of the employees, it makes more sense to always use a getter instead of placing these in a separate array in the state.
Some other notes:
- You mutations are called get... while these are setters, it might be best to rename these.
- In your action, you currently set the same result as employees and sysAdmins. Again, I would just set employees and always filter the sysAdmins from that array.
try this..
check the result using console.log to make it sure.
const newValue = {
...JSON.parse(localStorage.getItem("Employees")),
department.id: 3
}
localStorage.setItem("Employees", JSON.stringify(newValue))
or
// Get the user from localStorage and parse into object
let department = JSON.parse(localStorage.getItem("Employees"));
// Update an attribute on the user object
Employees.department.id = 2;
// Update the user in localStorage and stringify to string
localStorage.setItem("Employees", JSON.stringify(Employees));

How retrieve intent slot value, drive me crazy

I simply want to retrieve to slot value on code, I wanna try to do a simple skill who respond in different ways according to day sopeak from users.
This is my sample code, I'm trying in blank project for don't have other issue.
The intent is "HelloWorldIntent" the slot is "day"
JSON:
{
"interactionModel": {
"languageModel": {
"invocationName": "try",
"intents": [
{
"name": "AMAZON.CancelIntent",
"samples": []
},
{
"name": "AMAZON.HelpIntent",
"samples": []
},
{
"name": "AMAZON.StopIntent",
"samples": []
},
{
"name": "HelloWorldIntent",
"slots": [
{
"name": "day",
"type": "AMAZON.DayOfWeek"
}
],
"samples": [
"good {day}",
"hello",
"how are you",
"say hi world",
"say hi",
"hi",
"say hello world",
"say hello"
]
},
{
"name": "AMAZON.NavigateHomeIntent",
"samples": []
}
],
"types": []
}
}
}
The index.js is:
const HelloWorldIntentHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'IntentRequest'
&& handlerInput.requestEnvelope.request.intent.name === 'HelloWorldIntent';
},
handle(handlerInput) {
var app = this.event.request.intent.slots.day.value;
const speechText = app;
return handlerInput.responseBuilder
.speak(speechText)
//.reprompt('add a reprompt if you want to keep the session open for the user to respond')
.getResponse();
}
};
When I ask good Monday (or any other day) the result is Sorry, I couldn't understand what you said. Please try again.
Any suggestion?
This is your issue:
var app = this.event.request.intent.slots.day.value;
That looks like code for the v1 of the SDK.
It looks like you're actually using v2 - if you have the most recent version, to get a slot value you can do this:
// Require the SDK at the top of your file
const Alexa = require('ask-sdk');
// Then in your handle function where you want the slot value
handle (handlerInput) {
const { requestEnvelope } = handlerInput;
const speechText = Alexa.getSlotValue(requestEnvelope, 'day');
return handlerInput.responseBuilder.speak(speechText).getResponse();
}
Alternatively, you could also get it like this:
const speechText = handlerInput.requestEnvelope.request.intent.slots['day'].value
Request Envelope Utils - ASK SDK v2

How to use the post_poll method in Zapier CLI

According to the docs, I should use a post_poll function to add the missing id field in the response.
How do I add the post_poll function ?
Here's my error:
Results must be an array, got: object,
({"totalevents":83,"events":[{"eventid":10266033,"c)
- Got a result missing the "id" property (83)
Tried following this but it is not clear to me, I'm very new to Zapier-CLI
Update - adding code
This is the function that returns the data:
const listEvents = (z, bundle) => {
console.log('listing events.. ');
let client_id = bundle.inputData.client_id;
const requestOpts = {
url: `https://wccqa.on24.com/wcc/api/v2/client/${client_id}/event`
};
return z.request(requestOpts)
.then((response) => {
return z.JSON.parse(response.content);
});
};
The sample response is the following, with the distiction that I added the id param manually to avoid errors when zapier test|push:
{
"id": 9964513,
"eventid": 9964513,
"archivestart": "2017-09-21T10:30:00-07:00",
"archiveend": "2018-09-21T10:30:00-07:00",
"description": "Zapier Event Test",
"iseliteexpired": "N",
"displaytimezonecd": "America/Bogota",
"eventtype": "Live Webcam ",
"regrequired": true,
"clientid": 22921,
"liveend": "2017-09-21T10:00:00-07:00",
"createtimestamp": "2017-09-21T09:47:44-07:00",
"audienceurl": "https://localhost.on24.com/wcc/r/9964513/C49755A02229BD48E6010848D7C81EF8",
"lastmodified": "2017-09-21T09:47:44-07:00",
"livestart": "2017-09-21T08:45:00-07:00",
"goodafter": "2017-09-21T09:00:00-07:00",
"regnotificationrequired": true,
"isactive": true,
"localelanguagecd": "en"
}
The ACTUAL response from the endpoint the following which is used in the app created in the Web Builder App instead of CLI and works fine:
{
"events": [
{
"eventid": 9964513,
"archivestart": "2017-09-21T10:30:00-07:00",
"archiveend": "2018-09-21T10:30:00-07:00",
"description": "Zapier Event Test",
"iseliteexpired": "N",
"displaytimezonecd": "America/Bogota",
"eventtype": "Live Webcam ",
"regrequired": true,
"clientid": 22921,
"liveend": "2017-09-21T10:00:00-07:00",
"createtimestamp": "2017-09-21T09:47:44-07:00",
"audienceurl": "https://localhost.on24.com/wcc/r/9964513/C49755A02229BD48E6010848D7C81EF8",
"lastmodified": "2017-09-21T09:47:44-07:00",
"livestart": "2017-09-21T08:45:00-07:00",
"goodafter": "2017-09-21T09:00:00-07:00",
"regnotificationrequired": true,
"isactive": true,
"localelanguagecd": "en"
}
],
"totalevents": 1
}
I was thinking something along the line of the following, but how do I register this ?
const postPoll = (event,z,bundle) => {
if(event.key === 'events'){
var results = z.JSON.parse(bundle.request.data).results;
var events = results.events.map(function(event){
event.id = event.eventid;
return event;
});
bundle.request.data = events;
}
};
module.exports = postPoll;
Nice, so you're almost there! CLI apps don't have pre_ and post_ poll methods. Instead, you put any manipulation after the response comes in.
const listEvents = (z, bundle) => {
console.log('listing events.. ');
let client_id = bundle.inputData.client_id;
const requestOpts = {
url: `https://wccqa.on24.com/wcc/api/v2/client/${client_id}/event`
};
return z.request(requestOpts)
.then((response) => {
return z.JSON.parse(response.content);
})
.then(data => {
const events = data.events; // array of events
return events.map(function(e){ // returns array of objects with `id` defined
e.id = e.event_id
return e
})
})
};

Resources