/// <summary>
        /// Stores or update scrum status data in Microsoft Azure Table storage.
        /// </summary>
        /// <param name="scrumStatusData">Holds scrum status entity data.</param>
        /// <returns>A task that represents scrum status entity data is saved or updated.</returns>
        public async Task <bool> CreateOrUpdateScrumStatusAsync(ScrumStatus scrumStatusData)
        {
            try
            {
                ScrumStatus scrumStatusDataEntity = new ScrumStatus()
                {
                    PartitionKey             = scrumStatusData?.SummaryCardId.Trim() + "_" + scrumStatusData.Username,
                    TodayTaskDescription     = scrumStatusData.TodayTaskDescription,
                    YesterdayTaskDescription = scrumStatusData.YesterdayTaskDescription,
                    BlockerDescription       = scrumStatusData.BlockerDescription,
                    SummaryCardId            = scrumStatusData.SummaryCardId.Trim(),
                    Username             = scrumStatusData.Username,
                    AadObjectId          = scrumStatusData.AadObjectId,
                    MembersActivityIdMap = scrumStatusData.MembersActivityIdMap,
                    RowKey    = scrumStatusData.SummaryCardId.Trim(),
                    CreatedOn = scrumStatusData.CreatedOn,
                };

                await this.EnsureInitializedAsync();

                TableOperation operation = TableOperation.InsertOrReplace(scrumStatusDataEntity);
                var            result    = await this.CloudTable.ExecuteAsync(operation);

                return(result.HttpStatusCode == (int)HttpStatusCode.NoContent);
            }
            catch (Exception ex)
            {
                this.logger.LogError(ex, $"An error occurred in CreateOrUpdateScrumStatusAsync: {JsonConvert.SerializeObject(scrumStatusData)}. {ex.Message}", SeverityLevel.Error);
                throw;
            }
        }
예제 #2
0
        /// <summary>
        /// Resume the scrum meeting
        /// </summary>
        /// <param name="scrum"></param>
        /// <param name="groupName"></param>
        /// <param name="accessToken"></param>
        /// <returns>scrum resume message along with the next question</returns>
        private string ScrumResume(Scrum scrum, string groupName, string accessToken)
        {
            ScrumStatus status    = FetchScrumStatus(groupName, accessToken, null, null, null).Result;
            var         returnMsg = string.Empty;

            //keyword encountered is "scrum resume"
            if (status == (ScrumStatus.Halted))
            {
                //scrum resumed
                scrum.IsHalted = false;
                _scrumRepository.Update(scrum);
                //when the scrum is resumed then, the next question is to be asked
                returnMsg += _stringConstant.ScrumResumed + GetQuestion(scrum.Id, groupName, null, null, scrum.ProjectId, accessToken).Result;
                return(returnMsg);
            }
            else if (status == (ScrumStatus.OnGoing))
            {
                returnMsg += _stringConstant.ScrumNotHalted + GetQuestion(scrum.Id, groupName, null, null, scrum.ProjectId, accessToken).Result;
                return(returnMsg);
            }
            else
            {
                return(ReplyToClient(status) + _stringConstant.ScrumCannotBeResumed);
            }
        }
예제 #3
0
        /// <summary>
        /// This method will be called when the keyword "leave @username" or "later @username" or "scrum @username" is received as reply from a group member. - JJ
        /// </summary>
        /// <param name="groupName"></param>
        /// <param name="userName"></param>
        /// <param name="leaveApplicant"></param>
        /// <param name="parameter"></param>
        /// <returns>Question to the next person or other scrum status</returns>
        private async Task <string> Leave(string groupName, string userName, string applicant)
        {
            var          returnMsg = string.Empty;
            List <Scrum> scrumList = _scrumRepository.Fetch(x => String.Compare(x.GroupName, groupName, true) == 0 && x.ScrumDate.Date == DateTime.UtcNow.Date).ToList();

            if (scrumList.Count > 0)
            {
                if (scrumList.FirstOrDefault().IsOngoing)
                {
                    if (!scrumList.FirstOrDefault().IsHalted)
                    {
                        // getting user name from user's slack name
                        var applicationUser = _applicationUser.FirstOrDefault(x => x.SlackUserName == userName);
                        // getting access token for that user
                        if (applicationUser != null)
                        {
                            // get access token of user for promact oauth server
                            var accessToken = await _attachmentRepository.AccessToken(applicationUser.UserName);

                            List <Question> questions = _questionRepository.Fetch(x => x.Type == 1).OrderBy(x => x.OrderNumber).ToList();
                            List <User>     employees = await _projectUser.GetUsersByGroupName(groupName, accessToken);

                            ScrumStatus scrumStatus = FetchScrumStatus(groupName, accessToken, null, employees, questions).Result;

                            if (scrumStatus == ScrumStatus.OnGoing)
                            {
                                var scrum = _scrumRepository.Fetch(x => String.Compare(x.GroupName, groupName, true) == 0 && x.ScrumDate.Date == DateTime.UtcNow.Date).FirstOrDefault();
                                List <ScrumAnswer> scrumAnswer = _scrumAnswerRepository.Fetch(x => x.ScrumId == scrum.Id).ToList();

                                //keyword "leave @username"
                                returnMsg = LeaveLater(scrumAnswer, employees, scrum.Id, applicant, questions, groupName, scrum.ProjectId, userName, accessToken);
                            }
                            else
                            {
                                returnMsg = ReplyToClient(scrumStatus);
                            }
                        }
                        else
                        {
                            // if user doesn't exist then this message will be shown to user
                            returnMsg = _stringConstant.YouAreNotInExistInOAuthServer;
                        }
                    }
                    else
                    {
                        returnMsg = _stringConstant.ScrumIsHalted;
                    }
                }
                else
                {
                    returnMsg = _stringConstant.ScrumAlreadyConducted;
                }
            }
            else
            {
                returnMsg = _stringConstant.ScrumNotStarted;
            }
            return(returnMsg);
        }
        /// <summary>
        /// Delete scrum status entity from Microsoft Azure Table storage.
        /// </summary>
        /// <param name="scrumStatus">Holds scrum status entity data.</param>
        /// <returns>Delete operation response.</returns>
        public async Task <TableResult> DeleteEntityAsync(ScrumStatus scrumStatus)
        {
            await this.EnsureInitializedAsync();

            TableOperation deleteOperation = TableOperation.Delete(scrumStatus);

            return(await this.CloudTable.ExecuteAsync(deleteOperation));
        }
예제 #5
0
        /// <summary>
        /// Select the appropriate reply to the client
        /// </summary>
        /// <param name="scrumStatus"></param>
        /// <returns>appropriate message indicating the status of scrum</returns>
        private string ReplyToClient(ScrumStatus scrumStatus)
        {
            string returnMessage = string.Empty;

            switch (scrumStatus)
            {
            case ScrumStatus.Completed:
                returnMessage = _stringConstant.ScrumAlreadyConducted;
                break;

            case ScrumStatus.Halted:
                returnMessage = _stringConstant.ScrumIsHalted;
                break;

            case ScrumStatus.NoEmployee:
                returnMessage = _stringConstant.NoEmployeeFound;
                break;

            case ScrumStatus.NoProject:
                returnMessage = _stringConstant.NoProjectFound;
                break;

            case ScrumStatus.InActiveProject:
                returnMessage = _stringConstant.ProjectInActive;
                break;

            case ScrumStatus.NoQuestion:
                returnMessage = _stringConstant.NoQuestion;
                break;

            case ScrumStatus.NotStarted:
                returnMessage = _stringConstant.ScrumNotStarted;
                break;

            case ScrumStatus.OnGoing:
                returnMessage = _stringConstant.ScrumInProgress;
                break;

            default: return(null);
            }
            return(returnMessage);
        }
예제 #6
0
        /// <summary>
        /// Halt the scrum meeting
        /// </summary>
        /// <param name="scrum"></param>
        /// <param name="groupName"></param>
        /// <param name="accessToken"></param>
        /// <returns>scrum halted message</returns>
        private string ScrumHalt(Scrum scrum, string groupName, string accessToken)
        {
            ScrumStatus status = FetchScrumStatus(groupName, accessToken, null, null, null).Result;

            //keyword encountered is "scrum halt"
            if (status == (ScrumStatus.OnGoing))
            {
                //scrum halted
                scrum.IsHalted = true;
                _scrumRepository.Update(scrum);
                return(_stringConstant.ScrumHalted);
            }
            else if (status == (ScrumStatus.Halted))
            {
                return(_stringConstant.ScrumAlreadyHalted);
            }
            else
            {
                return(ReplyToClient(status) + _stringConstant.ScrumCannotBeHalted);
            }
        }
예제 #7
0
        /// <summary>
        /// This method will be called when the keyword "scrum time" is encountered
        /// </summary>
        /// <param name="groupName"></param>
        /// <param name="userName"></param>
        /// <param name="accessToken"></param>
        /// <returns>The next question or the scrum complete message</returns>
        private async Task <string> StartScrum(string groupName, string userName, string accessToken)
        {
            string    replyMessage = string.Empty;
            ProjectAc project      = await _projectUser.GetProjectDetails(groupName, accessToken);

            List <User> employees = await _projectUser.GetUsersByGroupName(groupName, accessToken);

            List <Question> questionList = _questionRepository.Fetch(x => x.Type == 1).OrderBy(x => x.OrderNumber).ToList();
            ScrumStatus     scrumStatus  = FetchScrumStatus(groupName, accessToken, project, employees, questionList).Result;

            if (scrumStatus == ScrumStatus.NotStarted)
            {
                Question question = questionList.FirstOrDefault();
                Scrum    scrum    = new Scrum();
                scrum.CreatedOn    = DateTime.UtcNow;
                scrum.GroupName    = groupName;
                scrum.ScrumDate    = DateTime.UtcNow.Date;
                scrum.ProjectId    = project.Id;
                scrum.TeamLeaderId = project.TeamLeaderId;
                scrum.IsHalted     = false;
                scrum.IsOngoing    = true;
                _scrumRepository.Insert(scrum);

                User firstEmployee = employees.FirstOrDefault();
                //first employee is asked questions along with the previous day status (if any)
                replyMessage = _stringConstant.GoodDay + "<@" + firstEmployee.SlackUserName + ">!\n" + FetchPreviousDayStatus(firstEmployee.Id, project.Id) + question.QuestionStatement;
            }

            else if (scrumStatus == ScrumStatus.OnGoing)
            {
                //if scrum meeting was interrupted. "scrum time" is written to resume scrum meeting. So next question is fetched.
                var scrumList = _scrumRepository.Fetch(x => String.Compare(x.GroupName, groupName, true) == 0 && x.ScrumDate.Date == DateTime.UtcNow.Date).ToList();
                replyMessage = await GetQuestion(scrumList.FirstOrDefault().Id, groupName, null, null, project.Id, accessToken);
            }
            else
            {
                return(ReplyToClient(scrumStatus));
            }
            return(replyMessage);
        }
예제 #8
0
        /// <summary>
        /// When OnTurn method receives a submit invoke activity on bot turn, it calls this method.
        /// </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="cancellationToken">Propagates notification that operations should be canceled.</param>
        /// <returns>A task that represents a task module response.</returns>
        /// <remarks>
        /// Reference link: https://docs.microsoft.com/en-us/dotnet/api/microsoft.bot.builder.teams.teamsactivityhandler.onteamstaskmodulesubmitasync?view=botbuilder-dotnet-stable.
        /// </remarks>
        protected override async Task <TaskModuleResponse> OnTeamsTaskModuleSubmitAsync(
            ITurnContext <IInvokeActivity> turnContext,
            TaskModuleRequest taskModuleRequest,
            CancellationToken cancellationToken)
        {
            try
            {
                turnContext = turnContext ?? throw new ArgumentNullException(nameof(turnContext));
                this.RecordEvent(nameof(this.OnTeamsTaskModuleSubmitAsync), turnContext);

                var activity = turnContext.Activity;

                var         activityValue = JObject.Parse(activity.Value?.ToString())["data"].ToString();
                ScrumStatus scrumStatus   = JsonConvert.DeserializeObject <ScrumStatus>(activityValue);
                AdaptiveSubmitActionData adaptiveSubmitActionData = JsonConvert.DeserializeObject <AdaptiveSubmitActionData>(activityValue);

                if (scrumStatus == null || adaptiveSubmitActionData == null)
                {
                    this.logger.LogInformation("Value obtained from task module submit action is null");
                    return(this.cardHelper.GetTaskModuleErrorResponse(this.localizer.GetString("ErrorMessage"), this.localizer.GetString("BotFailureTitle")));
                }

                this.logger.LogInformation($"OnTeamsTaskModuleSubmitAsync: {JObject.Parse(activity.Value.ToString())["data"]}");

                switch (adaptiveSubmitActionData.AdaptiveActionType.ToUpperInvariant())
                {
                case Constants.UpdateStatusTaskModuleCommand:
                    string scrumStartActivityId = adaptiveSubmitActionData.ScrumStartActivityId;
                    string scrumMembers         = adaptiveSubmitActionData.ScrumMembers;
                    string scrumMasterId        = adaptiveSubmitActionData.ScrumMasterId;
                    if (string.IsNullOrWhiteSpace(scrumStatus.YesterdayTaskDescription) || string.IsNullOrWhiteSpace(scrumStatus.TodayTaskDescription))
                    {
                        return(this.cardHelper.GetScrumStatusValidationCardResponse(scrumMembers, scrumMasterId, scrumStartActivityId, scrumStatus));
                    }

                    this.logger.LogInformation($"Getting scrum master details which are active. ScrumMasterId: {scrumMasterId}");
                    var scrumMasterDetails = await this.scrumMasterStorageProvider.GetScrumMasterDetailsByScrumMasterIdAsync(scrumMasterId);

                    if (scrumMasterDetails == null || !scrumMasterDetails.IsActive)
                    {
                        this.logger.LogInformation($"Scrum master details for the scrum master id: {scrumMasterId} could not be found or scrum is inactive");
                        return(this.cardHelper.GetTaskModuleErrorResponse(string.Format(CultureInfo.CurrentCulture, this.localizer.GetString("ErrorScrumMasterDetailsNullOrInactive"), activity.From.Name), this.localizer.GetString("UpdateStatusTitle")));
                    }

                    var scrum = (await this.scrumStorageProvider.GetScrumByScrumStartActivityIdAsync(scrumStartActivityId)).FirstOrDefault();
                    await this.scrumHelper.SaveScrumStatusDetailsAsync(turnContext, scrumStatus, adaptiveSubmitActionData, scrum?.ScrumStartCardResponseId);

                    var membersActivityIdMap = JsonConvert.DeserializeObject <Dictionary <string, string> >(scrumMembers);
                    var updatedScrumSummary  = await this.scrumHelper.GetScrumSummaryAsync(scrumMasterId, scrum?.ScrumStartCardResponseId, membersActivityIdMap);

                    await this.cardHelper.UpdateSummaryCardAsync(updatedScrumSummary, scrum?.ScrumStartCardResponseId, scrumMasterId, scrumStartActivityId, membersActivityIdMap, scrumMasterDetails.TimeZone, turnContext, cancellationToken);

                    return(null);

                default:
                    return(null);
                }
            }
            catch (Exception ex)
            {
                this.logger.LogError(ex, "Error while submitting task module.", SeverityLevel.Error);
                return(this.cardHelper.GetTaskModuleErrorResponse(this.localizer.GetString("ErrorMessage"), this.localizer.GetString("BotFailureTitle")));
            }
        }
예제 #9
0
        /// <summary>
        /// Get scrum status update card when user clicks on update status button.
        /// </summary>
        /// <param name="membersId">Members id to verify the user.</param>
        /// <param name="scrumMasterId">Scrum master id to show updated status.</param>
        /// <param name="scrumStartActivityId">Activity id of scrum start card.</param>
        /// <param name="scrumStatus">Scrum status information.</param>
        /// <param name="localizer">The current cultures' string localizer.</param>
        /// <param name="isYesterdayValidationFailure">Determines whether to show yesterday validation error.</param>
        /// <param name="isTodayValidationFailure">Determines whether to show today validation error.</param>
        /// <returns>Scrum status update card attachment.</returns>
        public static Attachment GetScrumStatusUpdateCard(string membersId, string scrumMasterId, string scrumStartActivityId, ScrumStatus scrumStatus, IStringLocalizer <Strings> localizer, bool isYesterdayValidationFailure = false, bool isTodayValidationFailure = false)
        {
            AdaptiveCard scrumStatusUpdateCard = new AdaptiveCard(Constants.AdaptiveCardVersion)
            {
                Body = new List <AdaptiveElement>
                {
                    new AdaptiveColumnSet
                    {
                        Columns = new List <AdaptiveColumn>
                        {
                            new AdaptiveColumn
                            {
                                Width = AdaptiveColumnWidth.Auto,
                                Items = new List <AdaptiveElement>
                                {
                                    new AdaptiveTextBlock
                                    {
                                        Size    = AdaptiveTextSize.Medium,
                                        Wrap    = true,
                                        Text    = localizer.GetString("UpdateStatusYesterdayDescriptionTitle"),
                                        Spacing = AdaptiveSpacing.None,
                                    },
                                },
                            },
                            new AdaptiveColumn
                            {
                                Items = new List <AdaptiveElement>
                                {
                                    new AdaptiveTextBlock
                                    {
                                        Size = AdaptiveTextSize.Medium,
                                        Wrap = true,
                                        Text = localizer.GetString("UpdateStatusYesterdayDescriptionErrorMessage"),
                                        HorizontalAlignment = AdaptiveHorizontalAlignment.Right,
                                        Color     = AdaptiveTextColor.Attention,
                                        IsVisible = isYesterdayValidationFailure,
                                    },
                                },
                            },
                        },
                    },
                    new AdaptiveTextInput
                    {
                        Spacing     = AdaptiveSpacing.Small,
                        Placeholder = localizer.GetString("UpdateStatusYesterdayDescriptionPlaceholder"),
                        IsMultiline = true,
                        Style       = AdaptiveTextInputStyle.Text,
                        Id          = "yesterdaytaskdescription",
                        MaxLength   = InputFieldMaximumLength,
                        Value       = scrumStatus?.YesterdayTaskDescription,
                    },
                    new AdaptiveColumnSet
                    {
                        Columns = new List <AdaptiveColumn>
                        {
                            new AdaptiveColumn
                            {
                                Width = AdaptiveColumnWidth.Auto,
                                Items = new List <AdaptiveElement>
                                {
                                    new AdaptiveTextBlock
                                    {
                                        Size    = AdaptiveTextSize.Medium,
                                        Wrap    = true,
                                        Text    = localizer.GetString("UpdateStatusTodayDescriptionTitle"),
                                        Spacing = AdaptiveSpacing.None,
                                    },
                                },
                            },
                            new AdaptiveColumn
                            {
                                Items = new List <AdaptiveElement>
                                {
                                    new AdaptiveTextBlock
                                    {
                                        Size = AdaptiveTextSize.Medium,
                                        Wrap = true,
                                        Text = localizer.GetString("UpdateStatusTodayDescriptionErrorMessage"),
                                        HorizontalAlignment = AdaptiveHorizontalAlignment.Right,
                                        Color     = AdaptiveTextColor.Attention,
                                        IsVisible = isTodayValidationFailure,
                                    },
                                },
                            },
                        },
                    },
                    new AdaptiveTextInput
                    {
                        Spacing     = AdaptiveSpacing.Small,
                        Placeholder = localizer.GetString("UpdateStatusTodayDescriptionPlaceholder"),
                        IsMultiline = true,
                        Style       = AdaptiveTextInputStyle.Text,
                        Id          = "todaytaskdescription",
                        MaxLength   = InputFieldMaximumLength,
                        Value       = scrumStatus.TodayTaskDescription,
                    },
                    new AdaptiveTextBlock
                    {
                        Size  = AdaptiveTextSize.Medium,
                        Wrap  = true,
                        Text  = localizer.GetString("UpdateStatusAnyBlockersTitle"),
                        Color = AdaptiveTextColor.Attention,
                    },
                    new AdaptiveTextInput
                    {
                        Spacing     = AdaptiveSpacing.Small,
                        Placeholder = localizer.GetString("UpdateStatusAnyBlockersPlaceholder"),
                        IsMultiline = true,
                        Style       = AdaptiveTextInputStyle.Text,
                        Id          = "blockerdescription",
                        MaxLength   = InputFieldMaximumLength,
                        Value       = scrumStatus.BlockerDescription,
                    },
                    new AdaptiveColumnSet
                    {
                        Columns = new List <AdaptiveColumn>
                        {
                            new AdaptiveColumn
                            {
                                Width = AdaptiveColumnWidth.Stretch,
                                Items = new List <AdaptiveElement>
                                { // Represents empty column required for alignment.
                                },
                            },
                        },
                    },
                    new AdaptiveColumnSet
                    {
                        Columns = new List <AdaptiveColumn>
                        {
                            new AdaptiveColumn
                            {
                                Width = AdaptiveColumnWidth.Stretch,
                                Items = new List <AdaptiveElement>
                                { // Represents empty column required for alignment.
                                },
                            },
                        },
                    },
                    new AdaptiveColumnSet
                    {
                        Columns = new List <AdaptiveColumn>
                        {
                            new AdaptiveColumn
                            {
                                Width = AdaptiveColumnWidth.Stretch,
                                Items = new List <AdaptiveElement>
                                { // Represents empty column required for alignment.
                                },
                            },
                        },
                    },
                },
            };

            scrumStatusUpdateCard.Actions.Add(
                new AdaptiveSubmitAction()
            {
                Title = localizer.GetString("UpdateStatusSubmitButtonText"),
                Data  = new AdaptiveSubmitActionData
                {
                    MsTeams = new CardAction
                    {
                        Type = Constants.TaskModuleSubmitType,
                    },
                    ScrumMembers         = membersId,
                    ScrumMasterId        = scrumMasterId,
                    ScrumStartActivityId = scrumStartActivityId,
                    AdaptiveActionType   = Constants.UpdateStatusTaskModuleCommand,
                },
            });

            var adaptiveCardAttachment = new Attachment()
            {
                ContentType = AdaptiveCard.ContentType,
                Content     = scrumStatusUpdateCard,
            };

            return(adaptiveCardAttachment);
        }
예제 #10
0
        /// <summary>
        /// Get user scrum status details card for viewing all user status details.
        /// </summary>
        /// <param name="scrumStatus">Scrum status details filled by a member.</param>
        /// <param name="member">Member information whose scrum status is to be showed.</param>
        /// <param name="applicationBasePath">Application base URL.</param>
        /// <param name="localizer">The current cultures' string localizer.</param>
        /// <param name="id">Unique id for each row.</param>
        /// <param name="userScrumStatus">Individual user scrum status i.e. Not started or completed.</param>
        /// <param name="isBlocked">Determine whether user is blocked.</param>
        /// <returns>Returns scrum details card attachment.</returns>
        public static List <AdaptiveElement> GetUserScrumStatusCard(ScrumStatus scrumStatus, TeamsChannelAccount member, string applicationBasePath, IStringLocalizer <Strings> localizer, int id, string userScrumStatus, bool isBlocked = false)
        {
            string cardContent = $"CardContent{id}";
            string chevronUp   = $"ChevronUp{id}";
            string chevronDown = $"ChevronDown{id}";
            List <AdaptiveElement> userScrumStatusDetails = new List <AdaptiveElement>
            {
                new AdaptiveColumnSet
                {
                    Separator = true,
                    Spacing   = AdaptiveSpacing.Medium,
                    Columns   = new List <AdaptiveColumn>
                    {
                        new AdaptiveColumn
                        {
                            VerticalContentAlignment = AdaptiveVerticalContentAlignment.Center,
                            Width = AdaptiveColumnWidth.Stretch,
                            Items = new List <AdaptiveElement>
                            {
                                new AdaptiveTextBlock
                                {
                                    Text = member?.Name,
                                    Wrap = true,
                                },
                            },
                        },
                        new AdaptiveColumn
                        {
                            VerticalContentAlignment = AdaptiveVerticalContentAlignment.Center,
                            Width = AdaptiveColumnWidth.Auto,
                            Items = new List <AdaptiveElement>
                            {
                                new AdaptiveTextBlock
                                {
                                    HorizontalAlignment = AdaptiveHorizontalAlignment.Left,
                                    Spacing             = string.Equals(userScrumStatus, localizer.GetString("ScrumStatusNotStarted"), StringComparison.OrdinalIgnoreCase) ? AdaptiveSpacing.Small : AdaptiveSpacing.None,
                                    Text = userScrumStatus,
                                    Wrap = true,
                                },
                            },
                        },
                        new AdaptiveColumn
                        {
                            VerticalContentAlignment = AdaptiveVerticalContentAlignment.Center,
                            Width = AdaptiveColumnWidth.Stretch,
                            Items = new List <AdaptiveElement>
                            {
                                new AdaptiveTextBlock
                                {
                                    HorizontalAlignment = AdaptiveHorizontalAlignment.Left,
                                    Spacing             = AdaptiveSpacing.None,
                                    Text      = localizer.GetString("ScrumDetailsUserIsBlocked"),
                                    Wrap      = true,
                                    Color     = AdaptiveTextColor.Attention,
                                    IsVisible = isBlocked,
                                },
                            },
                        },
                        new AdaptiveColumn
                        {
                            Id = chevronDown,
                            VerticalContentAlignment = AdaptiveVerticalContentAlignment.Center,
                            Width = AdaptiveColumnWidth.Auto,
                            Items = new List <AdaptiveElement>
                            {
                                new AdaptiveImage
                                {
                                    AltText      = "collapse",
                                    PixelWidth   = 16,
                                    PixelHeight  = 8,
                                    SelectAction = new AdaptiveToggleVisibilityAction
                                    {
                                        Title          = "collapse",
                                        Type           = "Action.ToggleVisibility",
                                        TargetElements = new List <AdaptiveTargetElement>
                                        {
                                            cardContent,
                                            chevronUp,
                                            chevronDown,
                                        },
                                    },
                                    Style = AdaptiveImageStyle.Default,
                                    Url   = new Uri(applicationBasePath + "/Artifacts/chevronDown.png"),
                                },
                            },
                        },
                        new AdaptiveColumn
                        {
                            Id        = chevronUp,
                            IsVisible = false,
                            VerticalContentAlignment = AdaptiveVerticalContentAlignment.Center,
                            Width = AdaptiveColumnWidth.Auto,
                            Items = new List <AdaptiveElement>
                            {
                                new AdaptiveImage
                                {
                                    AltText      = "expand",
                                    PixelWidth   = 16,
                                    PixelHeight  = 8,
                                    SelectAction = new AdaptiveToggleVisibilityAction
                                    {
                                        Title          = "expand",
                                        Type           = "Action.ToggleVisibility",
                                        TargetElements = new List <AdaptiveTargetElement>
                                        {
                                            cardContent,
                                            chevronUp,
                                            chevronDown,
                                        },
                                    },
                                    Style = AdaptiveImageStyle.Default,
                                    Url   = new Uri(applicationBasePath + "/Artifacts/chevronUp.png"),
                                },
                            },
                        },
                    },
                },
                new AdaptiveContainer
                {
                    Id        = cardContent,
                    IsVisible = false,
                    Items     = new List <AdaptiveElement>
                    {
                        new AdaptiveContainer
                        {
                            Items = new List <AdaptiveElement>
                            {
                                new AdaptiveTextBlock
                                {
                                    IsSubtle            = true,
                                    HorizontalAlignment = AdaptiveHorizontalAlignment.Left,
                                    Text = localizer.GetString("UpdateStatusYesterdayDescriptionTitle"),
                                    Wrap = true,
                                },
                                new AdaptiveContainer
                                {
                                    Spacing = AdaptiveSpacing.Small,
                                    Style   = AdaptiveContainerStyle.Emphasis,
                                    Items   = new List <AdaptiveElement>
                                    {
                                        new AdaptiveTextBlock
                                        {
                                            HorizontalAlignment = AdaptiveHorizontalAlignment.Left,
                                            Spacing             = AdaptiveSpacing.Small,
                                            Text = string.IsNullOrEmpty(scrumStatus?.YesterdayTaskDescription) ? string.Empty : scrumStatus?.YesterdayTaskDescription,
                                            Wrap = true,
                                        },
                                    },
                                },
                                new AdaptiveTextBlock
                                {
                                    IsSubtle            = true,
                                    HorizontalAlignment = AdaptiveHorizontalAlignment.Left,
                                    Text = localizer.GetString("UpdateStatusTodayDescriptionTitle"),
                                    Wrap = true,
                                },
                                new AdaptiveContainer
                                {
                                    Spacing = AdaptiveSpacing.Small,
                                    Style   = AdaptiveContainerStyle.Emphasis,
                                    Items   = new List <AdaptiveElement>
                                    {
                                        new AdaptiveTextBlock
                                        {
                                            HorizontalAlignment = AdaptiveHorizontalAlignment.Left,
                                            Spacing             = AdaptiveSpacing.Small,
                                            Text = string.IsNullOrEmpty(scrumStatus?.TodayTaskDescription) ? string.Empty : scrumStatus?.TodayTaskDescription,
                                            Wrap = true,
                                        },
                                    },
                                },
                                new AdaptiveTextBlock
                                {
                                    Color               = AdaptiveTextColor.Attention,
                                    IsSubtle            = true,
                                    HorizontalAlignment = AdaptiveHorizontalAlignment.Left,
                                    Text   = localizer.GetString("UpdateStatusAnyBlockersTitle"),
                                    Weight = AdaptiveTextWeight.Bolder,
                                    Wrap   = true,
                                },
                                new AdaptiveContainer
                                {
                                    Spacing = AdaptiveSpacing.Small,
                                    Style   = AdaptiveContainerStyle.Emphasis,
                                    Items   = new List <AdaptiveElement>
                                    {
                                        new AdaptiveTextBlock
                                        {
                                            Color = AdaptiveTextColor.Attention,
                                            HorizontalAlignment = AdaptiveHorizontalAlignment.Left,
                                            Spacing             = AdaptiveSpacing.Small,
                                            Text = string.IsNullOrEmpty(scrumStatus?.BlockerDescription) ? string.Empty : scrumStatus?.BlockerDescription,
                                            Wrap = true,
                                        },
                                    },
                                },
                            },
                        },
                    },
                },
            };

            return(userScrumStatusDetails);
        }
예제 #11
0
 /// <summary>
 /// Get scrum status validation card with errors listed.
 /// </summary>
 /// <param name="membersActivityIdMap">Members id who are part of the scrum.</param>
 /// <param name="scrumMasterId">Unique identifier for scrum master details.</param>
 /// <param name="scrumStartActivityId">Scrum start card activity Id.</param>
 /// <param name="scrumStatus">Scrum status details filled by user.</param>
 /// <returns>Returns scrum status validation card to be sent in response.</returns>
 public TaskModuleResponse GetScrumStatusValidationCardResponse(string membersActivityIdMap, string scrumMasterId, string scrumStartActivityId, ScrumStatus scrumStatus)
 {
     return(new TaskModuleResponse
     {
         Task = new TaskModuleContinueResponse
         {
             Value = new TaskModuleTaskInfo()
             {
                 Card = ScrumCard.GetScrumStatusUpdateCard(membersActivityIdMap, scrumMasterId, scrumStartActivityId, scrumStatus, this.localizer, string.IsNullOrWhiteSpace(scrumStatus?.YesterdayTaskDescription), string.IsNullOrWhiteSpace(scrumStatus?.TodayTaskDescription)),
                 Height = TaskModuleHeight,
                 Width = TaskModuleWidth,
                 Title = this.localizer.GetString("UpdateStatusTitle"),
             },
         },
     });
 }
예제 #12
0
 /// <summary>
 /// Get scrum status update adaptive card in response to be filled by scrum member.
 /// </summary>
 /// <param name="membersActivityIdMap">Members id who are part of the scrum.</param>
 /// <param name="scrumMasterId">Unique identifier for scrum master details.</param>
 /// <param name="scrumStartActivityId">Scrum start card activity Id.</param>
 /// <param name="scrumStatus">Scrum status details.</param>
 /// <returns>Returns scrum status update card to be displayed in task module.</returns>
 public TaskModuleResponse GetScrumStatusUpdateCardResponse(string membersActivityIdMap, string scrumMasterId, string scrumStartActivityId, ScrumStatus scrumStatus)
 {
     return(new TaskModuleResponse
     {
         Task = new TaskModuleContinueResponse
         {
             Value = new TaskModuleTaskInfo()
             {
                 Card = ScrumCard.GetScrumStatusUpdateCard(membersActivityIdMap, scrumMasterId, scrumStartActivityId, scrumStatus, this.localizer),
                 Height = TaskModuleHeight,
                 Width = TaskModuleWidth,
                 Title = this.localizer.GetString("UpdateStatusTitle"),
             },
         },
     });
 }
예제 #13
0
        /// <summary>
        /// Stores scrum status details in storage.
        /// </summary>
        /// <param name="turnContext">Context object containing information cached for a single turn of conversation with a user.</param>
        /// <param name="scrumStatus">Scrum status entity to be stored in table storage.</param>
        /// <param name="adaptiveSubmitActionData">Data submitted in task module.</param>
        /// <param name="scrumStartCardResponseId">Scrum start card response id.</param>
        /// <param name="aadGroupId">Azure Active Directory group Id.</param>
        /// <returns>Returns success or failure on whether data is stored in storage.</returns>
        public async Task <bool> SaveScrumStatusDetailsAsync(ITurnContext <IInvokeActivity> turnContext, ScrumStatus scrumStatus, AdaptiveSubmitActionData adaptiveSubmitActionData, string scrumStartCardResponseId, string aadGroupId)
        {
            scrumStatus = scrumStatus ?? throw new ArgumentNullException(nameof(scrumStatus));
            turnContext = turnContext ?? throw new ArgumentNullException(nameof(turnContext));

            scrumStatus.MembersActivityIdMap     = adaptiveSubmitActionData?.ScrumMembers;
            scrumStatus.ScrumStartCardResponseId = scrumStartCardResponseId;
            scrumStatus.CreatedOn       = DateTime.UtcNow.ToString(Constants.Rfc3339DateTimeFormat, CultureInfo.CurrentCulture);
            scrumStatus.Username        = turnContext.Activity.From.Name;
            scrumStatus.AadGroupId      = aadGroupId;
            scrumStatus.UserAadObjectId = turnContext.Activity.From.AadObjectId;
            return(await this.scrumStatusStorageProvider.CreateOrUpdateScrumStatusAsync(scrumStatus));
        }
예제 #14
0
 /// <summary>
 /// Stores scrum status details in storage.
 /// </summary>
 /// <param name="turnContext">Context object containing information cached for a single turn of conversation with a user.</param>
 /// <param name="scrumStatus">Scrum status entity to be stored in table storage.</param>
 /// <param name="adaptiveSubmitActionData">Data submitted in task module.</param>
 /// <param name="summaryCardId">Scrum summary card id.</param>
 /// <returns>Returns success or failure on whether data is stored in storage.</returns>
 public async Task <bool> SaveScrumStatusDetailsAsync(ITurnContext <IInvokeActivity> turnContext, ScrumStatus scrumStatus, AdaptiveSubmitActionData adaptiveSubmitActionData, string summaryCardId)
 {
     scrumStatus = scrumStatus ?? throw new ArgumentNullException(nameof(scrumStatus));
     scrumStatus.MembersActivityIdMap = adaptiveSubmitActionData?.ScrumMembers;
     scrumStatus.SummaryCardId        = summaryCardId;
     scrumStatus.CreatedOn            = DateTime.UtcNow.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'", CultureInfo.CurrentCulture);
     scrumStatus.Username             = turnContext?.Activity.From.Name;
     scrumStatus.AadObjectId          = turnContext.Activity.From.AadObjectId;
     return(await this.scrumStatusStorageProvider.CreateOrUpdateScrumStatusAsync(scrumStatus));
 }