/// <summary>
        /// Store or update new hire introduction detail in Azure Table Storage.
        /// </summary>
        /// <param name="introductionEntity">Represents new hire introduction entity used for storage and retrieval.</param>
        /// <returns><see cref="Task"/> that represents new hire introduction entity is saved or updated.</returns>
        public async Task <bool> StoreOrUpdateIntroductionDetailAsync(IntroductionEntity introductionEntity)
        {
            introductionEntity = introductionEntity ?? throw new ArgumentNullException(nameof(introductionEntity));

            if (string.IsNullOrWhiteSpace(introductionEntity.NewHireAadObjectId) ||
                string.IsNullOrWhiteSpace(introductionEntity.ManagerAadObjectId) ||
                string.IsNullOrWhiteSpace(introductionEntity.NewHireConversationId) ||
                string.IsNullOrWhiteSpace(introductionEntity.ManagerConversationId) ||
                string.IsNullOrWhiteSpace(introductionEntity.NewHireQuestionnaire) ||
                string.IsNullOrWhiteSpace(introductionEntity.NewHireUserPrincipalName))
            {
                return(false);
            }

            var result = await this.InsertOrReplaceIntroductionAsync(introductionEntity);

            if (result == null)
            {
                return(false);
            }
            else
            {
                return(result.HttpStatusCode == (int)HttpStatusCode.NoContent);
            }
        }
        /// <summary>
        /// Stores or update new hire introduction data in Azure Table Storage.
        /// </summary>
        /// <param name="introductionEntity">Holds new hire introduction detail entity data.</param>
        /// <returns>A task that represents introduction entity data is saved or updated.</returns>
        private async Task <TableResult> InsertOrReplaceIntroductionAsync(IntroductionEntity introductionEntity)
        {
            await this.EnsureInitializedAsync();

            TableOperation addOrUpdateOperation = TableOperation.InsertOrReplace(introductionEntity);

            return(await this.CloudTable.ExecuteAsync(addOrUpdateOperation));
        }
Example #3
0
        public IntroductionEntity Create(EmployeeEntity EmployeeEntity, IntroductionEntity IntroductionEntity)
        {
            if (IntroductionEntity == null)
            {
                throw new NotFoundException();
            }
            Introduction Introduction = new Introduction(IntroductionEntity);

            UnitOfWork.IntroductionRepository.AddOrUpdate(Introduction);
            UnitOfWork.Complete();
            return(Get(EmployeeEntity, Introduction.Id));
        }
Example #4
0
        /// <summary>
        /// To generate the introduction entity.
        /// </summary>
        /// <param name="turnContext">Context object containing information cached for a single turn of conversation with a user.</param>
        /// <param name="taskModuleRequest">Task module invoke request value payload.</param>
        /// <param name="userDetails">Get user details.</param>
        /// <returns>Introduction entity.</returns>
        private async Task <IntroductionEntity> GenerateIntroductionEntityAsync(ITurnContext <IInvokeActivity> turnContext, TaskModuleRequest taskModuleRequest, TeamsChannelAccount userDetails)
        {
            var objects = (JObject)taskModuleRequest.Data;
            var count   = 0;
            List <IntroductionDetail> questionList;

            // Get Microsoft Graph token response.
            var response = await this.graphUtility.ObtainApplicationTokenAsync(
                this.botOptions.Value.TenantId,
                this.botOptions.Value.MicrosoftAppId,
                this.botOptions.Value.MicrosoftAppPassword);

            // Check if Microsoft Graph token is null.
            if (response == null)
            {
                this.logger.LogInformation("Response obtained from Microsoft Graph for access taken is null.");

                return(null);
            }

            questionList = (List <IntroductionDetail>) await this.sharePointHelper.GetIntroductionQuestionsAsync(response.AccessToken);

            var aboutMe = objects.Properties().Where(row => row.Name.Equals(CardConstants.NewHireProfileNoteInputId, StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault()?.Value.ToString();

            // Mapping question and answer based on question's unique id.
            foreach (var question in questionList)
            {
                question.Answer = objects.Properties().Where(row => row.Name == $"{CardConstants.QuestionId}{count}").FirstOrDefault()?.Value.ToString();
                count++;
            }

            IntroductionEntity introductionEntity = new IntroductionEntity
            {
                NewHireAadObjectId       = userDetails.AadObjectId,
                ManagerAadObjectId       = string.Empty,
                NewHireQuestionnaire     = JsonConvert.SerializeObject(questionList),
                ApprovalStatus           = (int)IntroductionStatus.PendingForApproval,
                Comments                 = null,
                NewHireName              = userDetails.Name,
                ManagerConversationId    = string.Empty,
                NewHireUserPrincipalName = userDetails.Email,
                NewHireConversationId    = turnContext.Activity.Conversation.Id,
                ApprovedOn               = null,
                NewHireProfileNote       = aboutMe,
            };

            return(introductionEntity);
        }
 /// <summary>
 /// Get introduction adaptive card.
 /// </summary>
 /// <param name="introductionEntity">New hire introduction details.</param>
 /// <param name="isAllQuestionAnswered">false if any of the question is not answered.</param>
 /// <returns>Envelope for Task Module Response.</returns>
 public TaskModuleResponse GetNewHireIntroductionCard(IntroductionEntity introductionEntity, bool isAllQuestionAnswered = true)
 {
     return(new TaskModuleResponse
     {
         Task = new TaskModuleContinueResponse
         {
             Value = new TaskModuleTaskInfo()
             {
                 Card = NewHireIntroductionCard.GetNewHireIntroductionCardAttachment(introductionEntity, this.localizer, this.botOptions.Value.AppBaseUri, isAllQuestionAnswered),
                 Height = isAllQuestionAnswered ? IntroductionTaskModuleHeight : ValidateIntroductionTaskModuleHeight,
                 Width = IntroductionTaskModuleWidth,
                 Title = this.localizer.GetString("AppTitle"),
             },
         },
     });
 }
 /// <summary>
 /// Get introduction detail adaptive card for hiring manager's team.
 /// </summary>
 /// <param name="introductionEntity">New hire introduction details.</param>
 /// <returns>Envelope for Task Module Response.</returns>
 public TaskModuleResponse GetIntroductionDetailCardForTeam(IntroductionEntity introductionEntity)
 {
     return(new TaskModuleResponse
     {
         Task = new TaskModuleContinueResponse
         {
             Value = new TaskModuleTaskInfo()
             {
                 Card = IntroductionDetailCard.GetCard(this.botOptions.Value.AppBaseUri, this.localizer, introductionEntity),
                 Height = IntroductionTaskModuleHeight,
                 Width = IntroductionDetailTaskModuleWidth,
                 Title = this.localizer.GetString("AppTitle"),
             },
         },
     });
 }
 /// <summary>
 /// Gets introduction validation card to show in task module.
 /// </summary>
 /// <param name="introductionEntity">New hire introduction details.</param>
 /// <returns>Envelope for Task Module Response.</returns>
 public TaskModuleResponse GetIntroductionValidationCard(IntroductionEntity introductionEntity)
 {
     return(new TaskModuleResponse
     {
         Task = new TaskModuleContinueResponse
         {
             Value = new TaskModuleTaskInfo()
             {
                 Card = TellMeMoreCard.GetValidationMessageCard(introductionEntity, this.localizer),
                 Height = ValidationMessageTaskModuleHeight,
                 Width = ValidationMessageTaskModuleWidth,
                 Title = this.localizer.GetString("AppTitle"),
             },
         },
     });
 }
Example #8
0
        /// <summary>
        /// This method will construct the introduction detail card for hiring manager's team.
        /// </summary>
        /// <param name="applicationBasePath">Application base path to get the logo of the application.</param>
        /// <param name="localizer">The current culture's string localizer.</param>
        /// <param name="introductionEntity">Introduction entity.</param>
        /// <returns>Introduction detail card attachment.</returns>
        public static Attachment GetCard(
            string applicationBasePath,
            IStringLocalizer <Strings> localizer,
            IntroductionEntity introductionEntity)
        {
            introductionEntity = introductionEntity ?? throw new ArgumentNullException(nameof(introductionEntity));

            var questionAnswerList = JsonConvert.DeserializeObject <List <IntroductionDetail> >(introductionEntity.NewHireQuestionnaire);

            AdaptiveCard card = new AdaptiveCard(new AdaptiveSchemaVersion(CardConstants.AdaptiveCardVersion))
            {
                Body = new List <AdaptiveElement>
                {
                    new AdaptiveImage
                    {
                        Url     = new Uri($"{applicationBasePath}/Artifacts/hiringManagerNotification.png"),
                        AltText = localizer.GetString("AlternativeText"),
                    },
                },
            };

            foreach (var questionAnswer in questionAnswerList)
            {
                card.Body.Add(
                    new AdaptiveTextBlock
                {
                    Weight  = AdaptiveTextWeight.Bolder,
                    Spacing = AdaptiveSpacing.Medium,
                    Text    = questionAnswer.Question,
                    Wrap    = true,
                });

                card.Body.Add(
                    new AdaptiveTextBlock
                {
                    Spacing = AdaptiveSpacing.Small,
                    Text    = questionAnswer.Answer,
                    Wrap    = true,
                });
            }

            return(new Attachment
            {
                ContentType = AdaptiveCard.ContentType,
                Content = card,
            });
        }
        /// <summary>
        /// Construct validation message card to show on task module.
        /// </summary>
        /// <param name="introductionEntity">New hire introduction details.</param>
        /// <param name="localizer">The current culture's string localizer.</param>
        /// <returns>Validation message card attachment.</returns>
        public static Attachment GetValidationMessageCard(IntroductionEntity introductionEntity, IStringLocalizer <Strings> localizer)
        {
            introductionEntity = introductionEntity ?? throw new ArgumentNullException(nameof(introductionEntity));

            AdaptiveCard validationCard = new AdaptiveCard(new AdaptiveSchemaVersion(CardConstants.AdaptiveCardVersion))
            {
                Body = new List <AdaptiveElement>
                {
                    new AdaptiveTextBlock
                    {
                        Text = introductionEntity.ApprovalStatus == (int)IntroductionStatus.PendingForApproval ? localizer.GetString("PendingMessageText") : localizer.GetString("ApprovedMessageText"),
                        Wrap = true,
                    },
                },
            };

            return(new Attachment
            {
                ContentType = AdaptiveCard.ContentType,
                Content = validationCard,
            });
        }
        /// <summary>
        /// Get confirmation card attachment to post a card to particular team.
        /// </summary>
        /// <param name="teamChannelMapping">Teams/Channel mappings.</param>
        /// <param name="localizer">The current culture's string localizer.</param>
        /// <param name="introductionEntity">New hire introduction details.</param>
        /// <param name="isTeamSelected">True if team selected.</param>
        /// <returns>Introduction confirmation card attachment.</returns>
        public static Attachment GetTeamConfirmationCard(List <Models.TeamDetail> teamChannelMapping, IStringLocalizer <Strings> localizer, IntroductionEntity introductionEntity, bool isTeamSelected = true)
        {
            introductionEntity = introductionEntity ?? throw new ArgumentNullException(nameof(introductionEntity));
            teamChannelMapping = teamChannelMapping ?? throw new ArgumentNullException(nameof(teamChannelMapping));

            var teamsChoices = new List <AdaptiveChoice>();

            foreach (var team in teamChannelMapping)
            {
                if (team.Channels != null)
                {
                    foreach (var channel in team.Channels)
                    {
                        teamsChoices.Add(new AdaptiveChoice()
                        {
                            Title = HttpUtility.HtmlEncode($"{team.TeamName} | {channel.ChannelName}"),

                            // binding team id and Channel id by ';' (semicolon)
                            Value = $"{team.TeamId};{channel.ChannelId}",
                        });
                    }
                }
            }

            AdaptiveCard card = new AdaptiveCard(CardConstants.AdaptiveCardVersion)
            {
                Body = new List <AdaptiveElement>
                {
                    new AdaptiveContainer()
                    {
                        PixelMinHeight = ContainerPixelHeight,
                        Items          = new List <AdaptiveElement>()
                        {
                            new AdaptiveTextBlock
                            {
                                Weight  = AdaptiveTextWeight.Bolder,
                                Spacing = AdaptiveSpacing.Medium,
                                Text    = localizer.GetString("TeamConfirmHeaderText"),
                                Wrap    = true,
                            },
                            new AdaptiveChoiceSetInput
                            {
                                Spacing = AdaptiveSpacing.Small,
                                Id      = TeamInputId,
                                Choices = teamsChoices,
                            },
                            new AdaptiveTextBlock
                            {
                                Size                = AdaptiveTextSize.Small,
                                Text                = localizer.GetString("RequiredFieldText"),
                                IsVisible           = !isTeamSelected,
                                HorizontalAlignment = AdaptiveHorizontalAlignment.Right,
                                Color               = AdaptiveTextColor.Attention,
                            },
                        },
                    },
                },

                Actions = new List <AdaptiveAction>
                {
                    new AdaptiveSubmitAction
                    {
                        Title = localizer.GetString("PostInTeamButtonText"),
                        Data  = new AdaptiveSubmitActionData
                        {
                            Command            = BotCommandConstants.PostTeamNotificationAction,
                            IntroductionEntity = introductionEntity,
                        },
                    },
                },
            };

            return(new Attachment
            {
                ContentType = AdaptiveCard.ContentType,
                Content = card,
            });
        }
Example #11
0
        public IntroductionEntity Update(EmployeeEntity EmployeeEntity, Guid IntroductionId, IntroductionEntity IntroductionEntity)
        {
            IntroductionEntity.Id = IntroductionId;
            Introduction Introduction = new Introduction(IntroductionEntity);

            UnitOfWork.IntroductionRepository.AddOrUpdate(Introduction);
            UnitOfWork.Complete();
            return(Get(EmployeeEntity, Introduction.Id));
        }
        /// <summary>
        /// Get notification card after approved introduction from hiring manager.
        /// </summary>
        /// <param name="applicationBasePath">Application base path to get the logo of the application.</param>
        /// <param name="localizer">The current culture's string localizer.</param>
        /// <param name="introductionEntity">New hire introduction details.</param>
        /// <returns>Team introduction card attachment.</returns>
        public static Attachment GetCard(
            string applicationBasePath,
            IStringLocalizer <Strings> localizer,
            IntroductionEntity introductionEntity)
        {
            introductionEntity = introductionEntity ?? throw new ArgumentNullException(nameof(introductionEntity));

            AdaptiveCard card = new AdaptiveCard(new AdaptiveSchemaVersion(CardConstants.AdaptiveCardVersion))
            {
                Body = new List <AdaptiveElement>
                {
                    new AdaptiveTextBlock
                    {
                        Text    = localizer.GetString("TeamNotificationHeaderText", introductionEntity.NewHireName),
                        Spacing = AdaptiveSpacing.Small,
                        Color   = AdaptiveTextColor.Accent,
                    },
                    new AdaptiveTextBlock
                    {
                        Weight  = AdaptiveTextWeight.Bolder,
                        Size    = AdaptiveTextSize.Large,
                        Spacing = AdaptiveSpacing.None,
                        Text    = introductionEntity.NewHireName,
                    },
                    new AdaptiveImage
                    {
                        Url                 = new Uri(!string.IsNullOrEmpty(introductionEntity.UserProfileImageUrl) ? introductionEntity.UserProfileImageUrl : $"{applicationBasePath}/Artifacts/peopleAvatar.png"),
                        Spacing             = AdaptiveSpacing.ExtraLarge,
                        PixelHeight         = IntroductionImageHeightInPixel,
                        PixelWidth          = IntroductionImageWidthInPixel,
                        HorizontalAlignment = AdaptiveHorizontalAlignment.Center,
                        Style               = AdaptiveImageStyle.Person,
                        AltText             = localizer.GetString("AlternativeText"),
                    },
                    new AdaptiveTextBlock
                    {
                        Text    = !string.IsNullOrEmpty(introductionEntity.NewHireProfileNote) ? introductionEntity.NewHireProfileNote : localizer.GetString("IntroductionGreetText", introductionEntity.NewHireName),
                        Spacing = AdaptiveSpacing.Small,
                        Wrap    = true,
                    },
                },
                Actions = new List <AdaptiveAction>
                {
                    new AdaptiveOpenUrlAction
                    {
                        Title = localizer.GetString("ChatButtonText", introductionEntity.NewHireName),
                        Url   = new Uri($"{DeepLinkConstants.ChatInitiateURL}?users={Uri.EscapeDataString(introductionEntity.NewHireUserPrincipalName)}"),
                    },
                    new AdaptiveSubmitAction
                    {
                        Title = localizer.GetString("SeeMoreDetailsButtonText"),
                        Data  = new AdaptiveSubmitActionData
                        {
                            Msteams = new CardAction
                            {
                                Type = CardConstants.FetchActionType,
                                Text = BotCommandConstants.SeeIntroductionDetailAction,
                            },
                            IntroductionEntity = introductionEntity,
                            Command            = BotCommandConstants.SeeIntroductionDetailAction,
                        },
                    },
                },
            };

            return(new Attachment
            {
                ContentType = AdaptiveCard.ContentType,
                Content = card,
            });
        }
        /// <summary>
        /// This method will construct the edit introduction card for new hire employee.
        /// </summary>
        /// <param name="applicationBasePath">Application base path to get the logo of the application.</param>
        /// <param name="localizer">The current culture's string localizer.</param>
        /// <param name="introductionEntity">New hire introduction details.</param>
        /// <returns>Tell me more card attachment.</returns>
        public static Attachment GetCard(
            string applicationBasePath,
            IStringLocalizer <Strings> localizer,
            IntroductionEntity introductionEntity)
        {
            introductionEntity = introductionEntity ?? throw new ArgumentNullException(nameof(introductionEntity));

            AdaptiveCard card = new AdaptiveCard(new AdaptiveSchemaVersion(CardConstants.AdaptiveCardVersion))
            {
                Body = new List <AdaptiveElement>
                {
                    new AdaptiveColumnSet
                    {
                        Columns = new List <AdaptiveColumn>
                        {
                            new AdaptiveColumn
                            {
                                Items = new List <AdaptiveElement>
                                {
                                    new AdaptiveTextBlock
                                    {
                                        Weight  = AdaptiveTextWeight.Bolder,
                                        Size    = AdaptiveTextSize.Large,
                                        Text    = localizer.GetString("EditIntroCardHeaderText"),
                                        Spacing = AdaptiveSpacing.Small,
                                        Wrap    = true,
                                    },
                                    new AdaptiveTextBlock
                                    {
                                        Spacing = AdaptiveSpacing.Small,
                                        Text    = localizer.GetString("EditIntroCardSubHeaderText"),
                                        Wrap    = true,
                                    },
                                    new AdaptiveTextBlock
                                    {
                                        Weight  = AdaptiveTextWeight.Bolder,
                                        Size    = AdaptiveTextSize.Medium,
                                        Spacing = AdaptiveSpacing.Small,
                                        Text    = localizer.GetString("ManagerCommentsTitleText"),
                                        Wrap    = true,
                                    },
                                    new AdaptiveTextBlock
                                    {
                                        Spacing = AdaptiveSpacing.Small,
                                        Text    = introductionEntity.Comments,
                                        Wrap    = true,
                                    },
                                },
                            },
                            new AdaptiveColumn
                            {
                                Items = new List <AdaptiveElement>
                                {
                                    new AdaptiveImage
                                    {
                                        Url  = new Uri($"{applicationBasePath}/Artifacts/moreInformationImage.png"),
                                        Size = AdaptiveImageSize.Large,
                                        HorizontalAlignment = AdaptiveHorizontalAlignment.Right,
                                        AltText             = localizer.GetString("AlternativeText"),
                                    },
                                },
                            },
                        },
                    },
                },
                Actions = new List <AdaptiveAction>
                {
                    new AdaptiveSubmitAction
                    {
                        Title = localizer.GetString("EditIntroButtonText"),
                        Data  = new AdaptiveSubmitActionData
                        {
                            Msteams = new CardAction
                            {
                                Type = CardConstants.FetchActionType,
                                Text = BotCommandConstants.IntroductionAction,
                            },
                            Command = BotCommandConstants.IntroductionAction,
                        },
                    },
                },
            };

            return(new Attachment
            {
                ContentType = AdaptiveCard.ContentType,
                Content = card,
            });
        }
Example #14
0
        /// <summary>
        /// Submit introduction card action.
        /// </summary>
        /// <param name="userGraphAccessToken">User access token.</param>
        /// <param name="turnContext">Provides context for a step in a bot dialog.</param>
        /// <param name="taskModuleRequest">Task module invoke request value payload.</param>
        /// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
        /// <returns>A task that returns submitted introduction card attachment as task module response.</returns>
        public async Task <TaskModuleResponse> SubmitIntroductionActionAsync(
            string userGraphAccessToken,
            ITurnContext <IInvokeActivity> turnContext,
            TaskModuleRequest taskModuleRequest,
            CancellationToken cancellationToken)
        {
            turnContext       = turnContext ?? throw new ArgumentNullException(nameof(turnContext));
            taskModuleRequest = taskModuleRequest ?? throw new ArgumentNullException(nameof(taskModuleRequest));

            var userDetails = await this.GetUserDetailAsync(turnContext, cancellationToken);

            IntroductionEntity introductionEntity = await this.GenerateIntroductionEntityAsync(
                turnContext,
                taskModuleRequest,
                userDetails);

            var questionnaire = JsonConvert.DeserializeObject <List <IntroductionDetail> >(introductionEntity.NewHireQuestionnaire);

            if (!questionnaire.Where(row => string.IsNullOrEmpty(row.Answer)).ToList().Any() &&
                !string.IsNullOrWhiteSpace(introductionEntity.NewHireProfileNote))
            {
                // Get Manager details from Microsoft Graph API.
                var myManager = await this.userProfileGraphApiHelper.GetMyManagerAsync(userGraphAccessToken);

                if (myManager == null)
                {
                    this.logger.LogWarning($"Error in getting manager details from Microsoft Graph API for user {turnContext.Activity.From.Id}.");
                    await turnContext.SendActivityAsync(this.localizer.GetString("UserNotMappedWithManagerMessageText"));

                    return(null);
                }

                // Get Manager's conversation id from storage.
                var userConversationDetails = await this.userStorageProvider.GetUserDetailAsync(myManager.Id);

                if (userConversationDetails == null)
                {
                    this.logger.LogWarning($"Error in getting user conversation details from storage for user {myManager.Id}.");
                    await turnContext.SendActivityAsync(this.localizer.GetString("ManagerUnavailableText"));

                    return(null);
                }

                introductionEntity.ManagerAadObjectId    = myManager.Id;
                introductionEntity.ManagerConversationId = userConversationDetails.ConversationId;

                await this.introductionStorageProvider.StoreOrUpdateIntroductionDetailAsync(introductionEntity);

                await turnContext.SendActivityAsync(this.localizer.GetString("IntroSubmittedMessage"));

                this.logger.LogInformation($"Introduction submitted by: {turnContext.Activity.From.Id}.");

                var hiringMangerNotification = MessageFactory.Attachment(HiringManagerNotificationCard.GetNewEmployeeIntroductionCard(this.botOptions.Value.AppBaseUri, this.localizer, introductionEntity));
                hiringMangerNotification.Conversation = new ConversationAccount {
                    Id = introductionEntity.ManagerConversationId
                };
                await turnContext.Adapter.SendActivitiesAsync(turnContext, new Activity[] { (Activity)hiringMangerNotification }, cancellationToken);

                return(null);
            }
            else
            {
                // send back introduction card with corresponding validation message.
                return(this.introductionCardHelper.GetNewHireIntroductionCard(introductionEntity, isAllQuestionAnswered: false));
            }
        }
Example #15
0
        /// <summary>
        /// Get new hire introduction card.
        /// </summary>
        /// <param name="userGraphAccessToken">User access token.</param>
        /// <param name="turnContext">Provides context for a step in a bot dialog.</param>
        /// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
        /// <returns>A task that returns introduction card attachment as task module response.</returns>
        public async Task <TaskModuleResponse> GetIntroductionAsync(
            string userGraphAccessToken,
            ITurnContext turnContext,
            CancellationToken cancellationToken)
        {
            turnContext = turnContext ?? throw new ArgumentNullException(nameof(turnContext));
            var userDetails = await this.GetUserDetailAsync(turnContext, cancellationToken);

            // Get Manager details from Microsoft Graph API.
            var myManager = await this.userProfileGraphApiHelper.GetMyManagerAsync(userGraphAccessToken);

            if (myManager == null)
            {
                this.logger.LogWarning($"Error in getting manager details from Microsoft Graph API for user {turnContext.Activity.From.Id}.");
                await turnContext.SendActivityAsync(this.localizer.GetString("GenericErrorMessageText"));

                return(null);
            }

            var introductionEntity = await this.introductionStorageProvider.GetIntroductionDetailAsync(userDetails.AadObjectId, myManager.Id);

            if (introductionEntity == null)
            {
                // Get Microsoft Graph token response.
                var response = await this.graphUtility.ObtainApplicationTokenAsync(
                    this.botOptions.Value.TenantId,
                    this.botOptions.Value.MicrosoftAppId,
                    this.botOptions.Value.MicrosoftAppPassword);

                // Check if Microsoft Graph token is null.
                if (response == null)
                {
                    this.logger.LogInformation("Response obtained from Microsoft Graph for access taken is null.");

                    return(null);
                }

                var introductionQuestions = await this.sharePointHelper.GetIntroductionQuestionsAsync(response.AccessToken);

                if (introductionQuestions == null)
                {
                    return(null);
                }

                var profileNote = await this.userProfileGraphApiHelper.GetUserProfileNoteAsync(userGraphAccessToken, userDetails.AadObjectId);

                introductionEntity = new IntroductionEntity
                {
                    NewHireAadObjectId       = userDetails.AadObjectId,
                    ManagerAadObjectId       = myManager.Id,
                    NewHireQuestionnaire     = JsonConvert.SerializeObject(introductionQuestions),
                    ApprovalStatus           = (int)IntroductionStatus.PendingForApproval,
                    Comments                 = null,
                    NewHireName              = userDetails.Name,
                    ManagerConversationId    = string.Empty,
                    NewHireUserPrincipalName = userDetails.Email,
                    NewHireConversationId    = userDetails.Id,
                    ApprovedOn               = null,
                    NewHireProfileNote       = profileNote,
                };

                return(this.introductionCardHelper.GetNewHireIntroductionCard(introductionEntity));
            }
            else if (introductionEntity != null && introductionEntity.ApprovalStatus != (int)IntroductionStatus.TellMeMore)
            {
                return(this.introductionCardHelper.GetIntroductionValidationCard(introductionEntity));
            }
            else
            {
                return(this.introductionCardHelper.GetNewHireIntroductionCard(introductionEntity));
            }
        }
        /// <summary>
        /// Get new employee introduction card attachment for hiring manager to show on Microsoft Teams personal scope.
        /// </summary>
        /// <param name="applicationBasePath">Application base path to get the logo of the application.</param>
        /// <param name="localizer">The current culture's string localizer.</param>
        /// <param name="introductionEntity">Introduction entity.</param>
        /// <returns>New employee introduction card attachment.</returns>
        public static Attachment GetNewEmployeeIntroductionCard(
            string applicationBasePath,
            IStringLocalizer <Strings> localizer,
            IntroductionEntity introductionEntity)
        {
            introductionEntity = introductionEntity ?? throw new ArgumentNullException(nameof(introductionEntity));

            var questionAnswerList = JsonConvert.DeserializeObject <List <IntroductionDetail> >(introductionEntity.NewHireQuestionnaire);

            AdaptiveCard card = new AdaptiveCard(new AdaptiveSchemaVersion(CardConstants.AdaptiveCardVersion))
            {
                Body = new List <AdaptiveElement>
                {
                    new AdaptiveImage
                    {
                        Url     = new Uri($"{applicationBasePath}/Artifacts/hiringManagerNotification.png"),
                        AltText = localizer.GetString("AlternativeText"),
                    },
                    new AdaptiveTextBlock
                    {
                        Weight  = AdaptiveTextWeight.Bolder,
                        Size    = AdaptiveTextSize.Large,
                        Spacing = AdaptiveSpacing.Medium,
                        Text    = introductionEntity.NewHireName,
                    },
                    new AdaptiveTextBlock
                    {
                        Spacing = AdaptiveSpacing.Small,
                        Text    = !string.IsNullOrWhiteSpace(introductionEntity.NewHireProfileNote) ? introductionEntity.NewHireProfileNote : localizer.GetString("IntroductionGreetText", introductionEntity.NewHireName),
                        Wrap    = true,
                    },
                },
                Actions = new List <AdaptiveAction>(),
            };

            foreach (var questionAnswer in questionAnswerList)
            {
                card.Body.Add(
                    new AdaptiveTextBlock
                {
                    Weight  = AdaptiveTextWeight.Bolder,
                    Spacing = AdaptiveSpacing.Medium,
                    Text    = questionAnswer.Question,
                    Wrap    = true,
                });

                card.Body.Add(
                    new AdaptiveTextBlock
                {
                    Spacing = AdaptiveSpacing.Small,
                    Text    = questionAnswer.Answer,
                    Wrap    = true,
                });
            }

            card.Actions.Add(
                new AdaptiveSubmitAction
            {
                Title = localizer.GetString("ApproveButtonText"),
                Data  = new AdaptiveSubmitActionData
                {
                    Msteams = new CardAction
                    {
                        Type = CardConstants.FetchActionType,
                        Text = BotCommandConstants.ApproveIntroductionAction,
                    },
                    Command            = BotCommandConstants.ApproveIntroductionAction,
                    IntroductionEntity = introductionEntity,
                },
            });

            card.Actions.Add(
                new AdaptiveShowCardAction()
            {
                Title = localizer.GetString("TellMeMoreButtonText"),
                Card  = GetMoreInfoCard(localizer, introductionEntity),
            });

            return(new Attachment
            {
                ContentType = AdaptiveCard.ContentType,
                Content = card,
            });
        }
Example #17
0
 public IntroductionEntity Create([FromBody] IntroductionEntity IntroductionEntity)
 {
     return(IntroductionService.Create(EmployeeEntity, IntroductionEntity));
 }
 /// <summary>
 /// Get team confirmation adaptive card.
 /// </summary>
 /// <param name="teamChannelMapping">Teams/Channel mappings.</param>
 /// <param name="introductionEntity">New hire introduction details.</param>
 /// <param name="isTeamSelected">false if not team has selected.</param>
 /// <returns>Envelope for Task Module Response.</returns>
 public TaskModuleResponse GetApproveDetailCard(List <Models.TeamDetail> teamChannelMapping, IntroductionEntity introductionEntity, bool isTeamSelected = true)
 {
     return(new TaskModuleResponse
     {
         Task = new TaskModuleContinueResponse
         {
             Value = new TaskModuleTaskInfo()
             {
                 Card = HiringManagerNotificationCard.GetTeamConfirmationCard(teamChannelMapping, this.localizer, introductionEntity, isTeamSelected),
                 Height = ApproveDetailTaskModuleHeight,
                 Width = ApproveDetailTaskModuleWidth,
                 Title = this.localizer.GetString("AppTitle"),
             },
         },
     });
 }
Example #19
0
        /// <summary>
        /// Get new hire introduction card attachment to show on Microsoft Teams personal scope.
        /// </summary>
        /// <param name="introductionEntity">New hire introduction details.</param>
        /// <param name="localizer">The current culture's string localizer.</param>
        /// <param name="applicationBasePath">Application base path to get the logo of the application.</param>
        /// <param name="isAllQuestionsAnswered">False when any of the question is not answered.</param>
        /// <returns>New Hire Introduction Card attachment.</returns>
        public static Attachment GetNewHireIntroductionCardAttachment(IntroductionEntity introductionEntity, IStringLocalizer <Strings> localizer, string applicationBasePath, bool isAllQuestionsAnswered = true)
        {
            introductionEntity = introductionEntity ?? throw new ArgumentNullException(nameof(introductionEntity));
            List <IntroductionDetail> questionAnswerList = JsonConvert.DeserializeObject <List <IntroductionDetail> >(introductionEntity.NewHireQuestionnaire);

            AdaptiveCard card = new AdaptiveCard(new AdaptiveSchemaVersion(CardConstants.AdaptiveCardVersion))
            {
                Body = new List <AdaptiveElement>
                {
                    new AdaptiveImage
                    {
                        Url     = new Uri($"{applicationBasePath}/Artifacts/introductionImage.png"),
                        AltText = localizer.GetString("AlternativeText"),
                    },
                    new AdaptiveTextBlock
                    {
                        Spacing = AdaptiveSpacing.Medium,
                        Text    = localizer.GetString("IntroductionText"),
                        Wrap    = true,
                    },
                    new AdaptiveTextBlock
                    {
                        Size    = AdaptiveTextSize.Small,
                        Spacing = AdaptiveSpacing.Small,
                        Text    = localizer.GetString("IntroductionHeaderText"),
                        Wrap    = true,
                    },
                    new AdaptiveTextInput
                    {
                        Spacing   = AdaptiveSpacing.Small,
                        Value     = !string.IsNullOrWhiteSpace(introductionEntity.NewHireProfileNote) ? introductionEntity.NewHireProfileNote : localizer.GetString("IntroductionGreetText", introductionEntity.NewHireName),
                        Id        = CardConstants.NewHireProfileNoteInputId,
                        MaxLength = 500,
                    },
                },
                Actions = new List <AdaptiveAction>
                {
                    new AdaptiveSubmitAction
                    {
                        Title = localizer.GetString("IntroductionSubmitButtonText"),
                        Data  = new AdaptiveSubmitActionData
                        {
                            Command = BotCommandConstants.SubmitIntroductionAction,
                        },
                    },
                },
            };

            foreach (var questionAnswer in questionAnswerList)
            {
                card.Body.Add(
                    new AdaptiveTextBlock
                {
                    Size    = AdaptiveTextSize.Medium,
                    Text    = questionAnswer.Question,
                    Wrap    = true,
                    Spacing = AdaptiveSpacing.Medium,
                });

                card.Body.Add(
                    new AdaptiveTextInput
                {
                    Id          = $"{CardConstants.QuestionId}{questionAnswerList.IndexOf(questionAnswer)}",
                    Spacing     = AdaptiveSpacing.Small,
                    Value       = !string.IsNullOrWhiteSpace(questionAnswer.Answer) ? questionAnswer.Answer : string.Empty,
                    MaxLength   = 500,
                    Placeholder = localizer.GetString("IntroductionInputPlaceholderText"),
                });
            }

            card.Body.Add(
                new AdaptiveTextBlock
            {
                Text      = localizer.GetString("ValidationMessageText"),
                Spacing   = AdaptiveSpacing.Medium,
                IsVisible = !isAllQuestionsAnswered,
                Color     = AdaptiveTextColor.Attention,
                Size      = AdaptiveTextSize.Small,
            });

            return(new Attachment
            {
                ContentType = AdaptiveCard.ContentType,
                Content = card,
            });
        }
Example #20
0
 public IntroductionEntity Update(Guid IntroductionId, [FromBody] IntroductionEntity IntroductionEntity)
 {
     return(IntroductionService.Update(EmployeeEntity, IntroductionId, IntroductionEntity));
 }
        /// <summary>
        /// Get more information card attachment to get more information about new hire employee.
        /// </summary>
        /// <param name="localizer">The current culture's string localizer.</param>
        /// <param name="introductionEntity">Introduction entity</param>
        /// <returns>Tell me more information card attachment.</returns>
        public static AdaptiveCard GetMoreInfoCard(IStringLocalizer <Strings> localizer, IntroductionEntity introductionEntity)
        {
            introductionEntity = introductionEntity ?? throw new ArgumentNullException(nameof(introductionEntity));

            AdaptiveCard card = new AdaptiveCard(CardConstants.AdaptiveCardVersion)
            {
                Body = new List <AdaptiveElement>
                {
                    new AdaptiveTextBlock
                    {
                        Weight  = AdaptiveTextWeight.Bolder,
                        Spacing = AdaptiveSpacing.Small,
                        Text    = localizer.GetString("MoreInfoCardSubHeaderText", introductionEntity.NewHireName),
                        Wrap    = true,
                    },
                    new AdaptiveTextInput
                    {
                        Id          = CommentsInputId,
                        Placeholder = localizer.GetString("CommentsPlaceHolderText"),
                        IsMultiline = true,
                        Height      = AdaptiveHeight.Stretch,
                        MaxLength   = 200,
                    },
                },
                Actions = new List <AdaptiveAction>
                {
                    new AdaptiveSubmitAction
                    {
                        Title = localizer.GetString("SendButtonText"),
                        Data  = new AdaptiveSubmitActionData
                        {
                            Msteams = new CardAction
                            {
                                Type = ActionTypes.MessageBack,
                                Text = BotCommandConstants.RequestMoreInfoAction,
                            },
                            IntroductionEntity = introductionEntity,
                        },
                    },
                },
            };

            return(card);
        }
Example #22
0
 public Introduction(IntroductionEntity IntroductionEntity) : base(IntroductionEntity)
 {
 }