示例#1
0
        /// <summary>
        /// Handle message activity in channel.
        /// </summary>
        /// <param name="message">A message in a conversation.</param>
        /// <param name="turnContext">Context object containing information cached for a single turn of conversation with a user.</param>
        /// <param name="onCallSupportDetailSearchService">Provider to search on call support details in Azure Table Storage.</param>
        /// <param name="ticketDetailStorageProvider">Provider to store ticket details to Azure Table Storage.</param>
        /// <param name="cardConfigurationStorageProvider">Provider to search card configuration details in Azure Table Storage.</param>
        /// <param name="logger">Sends logs to the Application Insights service.</param>
        /// <param name="appBaseUrl">Represents the Application base Uri.</param>
        /// <param name="localizer">The current cultures' string localizer.</param>
        /// <param name="cancellationToken">Propagates notification that operations should be canceled.</param>
        /// <returns>A task that represents the work queued to execute.</returns>
        internal static async Task OnMessageActivityInChannelAsync(
            IMessageActivity message,
            ITurnContext <IMessageActivity> turnContext,
            IOnCallSupportDetailSearchService onCallSupportDetailSearchService,
            ITicketDetailStorageProvider ticketDetailStorageProvider,
            ICardConfigurationStorageProvider cardConfigurationStorageProvider,
            ILogger logger,
            string appBaseUrl,
            IStringLocalizer <Strings> localizer,
            CancellationToken cancellationToken)
        {
            turnContext = turnContext ?? throw new ArgumentNullException(nameof(turnContext));
            if (!string.IsNullOrEmpty(message.ReplyToId) && message.Value != null && ((JObject)message.Value).HasValues)
            {
                logger.LogInformation($"Card submit in channel {message.Value?.ToString()}");
                await OnAdaptiveCardSubmitInChannelAsync(message : message, turnContext : turnContext, ticketDetailStorageProvider : ticketDetailStorageProvider, cardConfigurationStorageProvider : cardConfigurationStorageProvider, logger : logger, appBaseUrl : appBaseUrl, localizer : localizer, cancellationToken : cancellationToken);

                return;
            }

            turnContext.Activity.RemoveRecipientMention();
            string text = turnContext.Activity.Text.Trim();

            switch (text.ToUpperInvariant())
            {
            case Constants.ManageExpertsAction:
                // Get on call support data from storage
                var onCallSupportDetails = await onCallSupportDetailSearchService.SearchOnCallSupportTeamAsync(searchQuery : string.Empty, count : 10);

                var onCallSMEDetailActivity = MessageFactory.Attachment(OnCallSMEDetailCard.GetOnCallSMEDetailCard(onCallSupportDetails, localizer));
                var result = await turnContext.SendActivityAsync(onCallSMEDetailActivity);

                // Add activityId in the data which will be posted to task module in future after clicking on Manage button.
                AdaptiveCard       adaptiveCard = (AdaptiveCard)onCallSMEDetailActivity.Attachments?[0].Content;
                AdaptiveCardAction cardAction   = (AdaptiveCardAction)((AdaptiveSubmitAction)adaptiveCard?.Actions?[0]).Data;
                cardAction.ActivityId = result.Id;

                // Refresh manage experts card with activity Id bound to manage button.
                onCallSMEDetailActivity.Id        = result.Id;
                onCallSMEDetailActivity.ReplyToId = result.Id;
                await turnContext.UpdateActivityAsync(onCallSMEDetailActivity);

                break;

            default:
                logger.LogInformation("Unrecognized input in channel.");
                await turnContext.SendActivityAsync(MessageFactory.Attachment(WelcomeTeamCard.GetCard(appBaseUrl, localizer)));

                break;
            }
        }
示例#2
0
        /// <summary>
        /// Method updates experts card in team after modifying on call experts list.
        /// </summary>
        /// <param name="turnContext">Provides context for a turn of a bot.</param>
        /// <param name="onCallExpertsDetail">Details of on call support experts updated.</param>
        /// <param name="onCallSupportDetailSearchService">Provider to search on call support details in Azure Table Storage.</param>
        /// <param name="onCallSupportDetailStorageProvider"> Provider for fetching and storing information about on call support in storage table.</param>
        /// <param name="localizer">The current cultures' string localizer.</param>
        /// <returns>A task that sends notification in newly created channel and mention its members.</returns>
        public static async Task UpdateManageExpertsCardInTeamAsync(ITurnContext <IInvokeActivity> turnContext, OnCallExpertsDetail onCallExpertsDetail, IOnCallSupportDetailSearchService onCallSupportDetailSearchService, IOnCallSupportDetailStorageProvider onCallSupportDetailStorageProvider, IStringLocalizer <Strings> localizer)
        {
            // Get last 10 updated on call support data from storage.
            // This is required because search service refresh interval is 10 minutes. So we need to get latest entry stored in storage from storage provider and append previous 9 updated records to it in order to show on screen.
            var previousOnCallSupportDetails = await onCallSupportDetailSearchService?.SearchOnCallSupportTeamAsync(string.Empty, 9);

            var currentOnCallSupportDetails = await onCallSupportDetailStorageProvider?.GetOnCallSupportDetailAsync(onCallExpertsDetail?.OnCallSupportId);

            List <OnCallSupportDetail> onCallSupportDetails = new List <OnCallSupportDetail>
            {
                currentOnCallSupportDetails,
            };

            onCallSupportDetails.AddRange(previousOnCallSupportDetails);

            // Replace message id in conversation id with card activity id to be refreshed.
            var conversationId = turnContext?.Activity.Conversation.Id;

            conversationId = conversationId?.Replace(turnContext.Activity.Conversation.Id.Split(';')[1].Split("=")[1], onCallExpertsDetail?.OnCallSupportCardActivityId, StringComparison.OrdinalIgnoreCase);
            var onCallSMEDetailCardAttachment = OnCallSMEDetailCard.GetOnCallSMEDetailCard(onCallSupportDetails, localizer);

            // Add activityId in the data which will be posted to task module in future after clicking on Manage button.
            AdaptiveCard       adaptiveCard = (AdaptiveCard)onCallSMEDetailCardAttachment.Content;
            AdaptiveCardAction cardAction   = (AdaptiveCardAction)((AdaptiveSubmitAction)adaptiveCard?.Actions?[0]).Data;

            cardAction.ActivityId = onCallExpertsDetail?.OnCallSupportCardActivityId;

            // Update the card in the SME team with updated on call experts list.
            var updateExpertsCardActivity = new Activity(ActivityTypes.Message)
            {
                Id           = onCallExpertsDetail?.OnCallSupportCardActivityId,
                ReplyToId    = onCallExpertsDetail?.OnCallSupportCardActivityId,
                Conversation = new ConversationAccount {
                    Id = conversationId
                },
                Attachments = new List <Attachment> {
                    onCallSMEDetailCardAttachment
                },
            };
            await turnContext.UpdateActivityAsync(updateExpertsCardActivity);
        }
示例#3
0
        /// <summary>
        /// Method Handle adaptive card submit in 1:1 chat and Send new ticket details to SME team.
        /// </summary>
        /// <param name="message">Message activity of bot.</param>
        /// <param name="turnContext">Context object containing information cached for a single turn of conversation with a user.</param>
        /// <param name="ticketGenerateStorageProvider">Provider to get ticket id to Azure Table Storage.</param>
        /// <param name="ticketDetailStorageProvider">Provider to store ticket details to Azure Table Storage.</param>
        /// <param name="cardConfigurationStorageProvider">Provider to search card configuration details in Azure Table Storage.</param>
        /// <param name="microsoftAppCredentials">Microsoft Application credentials for Bot/ME.</param>
        /// <param name="logger">Sends logs to the Application Insights service.</param>
        /// <param name="appBaseUrl">Represents the Application base Uri.</param>
        /// <param name="localizer">The current cultures' string localizer.</param>
        /// <param name="cancellationToken">Propagates notification that operations should be canceled.</param>
        /// <returns>A task that handles submit action in 1:1 chat.</returns>
        internal static async Task OnAdaptiveCardSubmitInPersonalChatAsync(
            IMessageActivity message,
            ITurnContext <IMessageActivity> turnContext,
            ITicketIdGeneratorStorageProvider ticketGenerateStorageProvider,
            ITicketDetailStorageProvider ticketDetailStorageProvider,
            ICardConfigurationStorageProvider cardConfigurationStorageProvider,
            MicrosoftAppCredentials microsoftAppCredentials,
            ILogger logger,
            string appBaseUrl,
            IStringLocalizer <Strings> localizer,
            CancellationToken cancellationToken)
        {
            IMessageActivity endUserUpdateCard;

            switch (message.Text.ToUpperInvariant())
            {
            case Constants.SendRequestAction:
                TicketDetail newTicketDetail = JsonConvert.DeserializeObject <TicketDetail>(message.Value?.ToString());
                if (TicketHelper.ValidateRequestDetail(newTicketDetail))
                {
                    AdaptiveCardAction cardDetail = ((JObject)message.Value).ToObject <AdaptiveCardAction>();
                    logger.LogInformation("Adding new request with additional details.");
                    var ticketTd = await ticketGenerateStorageProvider.GetTicketIdAsync();

                    // Update new request with additional details.
                    var userDetails = await GetUserDetailsInPersonalChatAsync(turnContext, cancellationToken);

                    newTicketDetail.TicketId = ticketTd.ToString(CultureInfo.InvariantCulture);
                    newTicketDetail          = TicketHelper.GetNewTicketDetails(turnContext: turnContext, ticketDetail: newTicketDetail, ticketAdditionalDetails: message.Value?.ToString(), cardId: cardDetail.CardId, member: userDetails);
                    bool result = await ticketDetailStorageProvider.UpsertTicketAsync(newTicketDetail);

                    if (!result)
                    {
                        logger.LogError("Error in storing new ticket details in table storage.");
                        await turnContext.SendActivityAsync(localizer.GetString("AzureStorageErrorText"));

                        return;
                    }

                    logger.LogInformation("New request created with ticket Id:" + newTicketDetail.TicketId);

                    // Get card item element mappings
                    var carditemElementMapping = await cardConfigurationStorageProvider.GetCardItemElementMappingAsync(cardDetail?.CardId);

                    endUserUpdateCard = MessageFactory.Attachment(TicketCard.GetTicketDetailsForPersonalChatCard(carditemElementMapping, newTicketDetail, localizer, false));
                    await CardHelper.SendRequestCardToSMEChannelAsync(turnContext : turnContext, ticketDetail : newTicketDetail, logger : logger, ticketDetailStorageProvider : ticketDetailStorageProvider, applicationBasePath : appBaseUrl, cardElementMapping : carditemElementMapping, localizer, teamId : cardDetail?.TeamId, microsoftAppCredentials : microsoftAppCredentials, cancellationToken : cancellationToken);

                    await CardHelper.UpdateRequestCardForEndUserAsync(turnContext, endUserUpdateCard);

                    await turnContext.SendActivityAsync(MessageFactory.Text(localizer.GetString("EndUserNotificationText", newTicketDetail.TicketId)));
                }
                else
                {
                    // Update card with validation message.
                    newTicketDetail.AdditionalProperties = CardHelper.ValidateAdditionalTicketDetails(message.Value?.ToString(), timeSpan: turnContext.Activity.LocalTimestamp.Value.Offset);
                    CardConfigurationEntity cardTemplateJson = await cardConfigurationStorageProvider.GetConfigurationAsync();

                    endUserUpdateCard = MessageFactory.Attachment(TicketCard.GetNewTicketCard(cardConfiguration: cardTemplateJson, localizer: localizer, showValidationMessage: true, ticketDetail: newTicketDetail));
                    await CardHelper.UpdateRequestCardForEndUserAsync(turnContext, endUserUpdateCard);
                }

                break;

            case Constants.WithdrawRequestAction:
                var payload = ((JObject)message.Value).ToObject <AdaptiveCardAction>();
                endUserUpdateCard = MessageFactory.Attachment(WithdrawCard.GetCard(payload.PostedValues, localizer));

                // Get the ticket from the data store.
                TicketDetail ticketDetail = await ticketDetailStorageProvider.GetTicketAsync(payload.PostedValues);

                if (ticketDetail.TicketStatus == (int)TicketState.Kapatılmış)
                {
                    await turnContext.SendActivityAsync(localizer.GetString("WithdrawErrorMessage"));

                    return;
                }

                ticketDetail.LastModifiedByName     = message.From.Name;
                ticketDetail.LastModifiedByObjectId = message.From.AadObjectId;
                ticketDetail.TicketStatus           = (int)TicketState.Vazgeçilmiş;
                bool success = await ticketDetailStorageProvider.UpsertTicketAsync(ticketDetail);

                if (!success)
                {
                    logger.LogError("Error in updating ticket details in table storage.");
                    await turnContext.SendActivityAsync(localizer.GetString("AzureStorageErrorText"));

                    return;
                }

                logger.LogInformation("Withdrawn the ticket:" + ticketDetail.TicketId);
                IMessageActivity smeWithdrawNotification = MessageFactory.Text(localizer.GetString("SmeWithdrawNotificationText", ticketDetail.RequesterName));
                var itemElementMapping = await cardConfigurationStorageProvider.GetCardItemElementMappingAsync(ticketDetail?.CardId);

                await CardHelper.UpdateSMECardAsync(turnContext, ticketDetail, smeWithdrawNotification, appBaseUrl, itemElementMapping, localizer, logger, cancellationToken);

                await CardHelper.UpdateRequestCardForEndUserAsync(turnContext, endUserUpdateCard);

                break;
            }
        }
示例#4
0
        /// <summary>
        /// Validates endorsement status.
        /// </summary>
        /// <param name="turnContext">Context object containing information cached for a single turn of conversation with a user.</param>
        /// <param name="valuesforTaskModule">Get the binded values from the card.</param>
        /// <returns>Returns the true, if endorsement is successful, else false.</returns>
        private async Task <bool> CheckEndorseStatusAsync(ITurnContext <IInvokeActivity> turnContext, AdaptiveCardAction valuesforTaskModule)
        {
            var teamsDetails         = turnContext.Activity.TeamsGetTeamInfo();
            var teamsChannelAccounts = await TeamsInfo.GetTeamMembersAsync(turnContext, teamsDetails.Id, CancellationToken.None);

            var userDetails   = teamsChannelAccounts.Where(member => member.AadObjectId == turnContext.Activity.From.AadObjectId).FirstOrDefault();
            var endorseEntity = await this.endorseDetailStorageProvider.GetEndorseDetailAsync(teamsDetails.Id, valuesforTaskModule.RewardCycleId, valuesforTaskModule.NominatedToPrincipalName);

            var result = endorseEntity.Where(row => row.EndorseForAwardId == valuesforTaskModule.AwardId && row.EndorsedByObjectId == userDetails.AadObjectId).FirstOrDefault();

            if (result == null)
            {
                var endorsedetails = new EndorseEntity
                {
                    TeamId                  = teamsDetails.Id,
                    EndorsedByObjectId      = userDetails.AadObjectId,
                    EndorsedByPrincipalName = userDetails.Email,
                    EndorseForAward         = valuesforTaskModule.AwardName,
                    EndorsedToPrincipalName = valuesforTaskModule.NominatedToPrincipalName,
                    EndorsedToObjectId      = valuesforTaskModule.NominatedToObjectId,
                    EndorsedOn              = DateTime.UtcNow,
                    EndorseForAwardId       = valuesforTaskModule.AwardId,
                    AwardCycle              = valuesforTaskModule.RewardCycleId,
                };

                return(await this.endorseDetailStorageProvider.StoreOrUpdateEndorseDetailAsync(endorsedetails));
            }

            return(false);
        }