// TODO: A lot of this, like the fetch methods should probably be its own ProjectModel class - it's really about the // Project, not just the ProjectView and anything that's related to the view only (like the projectCategories) // can get pushed into the separate ProjectViewModel class that has a ProjectModel property on it. private async Task <ProjectViewModel> GetProjectViewModel(string id) { var projectCategories = _categoriesRepository.GetCategories(); var project = await _projectRepository.GetAsync(id); project.Status = StatusHelper.GetProjectStatusFromString(project.ProjectStatus); var projectDetailsAvatarIds = new List <string>(); projectDetailsAvatarIds.Add(project.AuthorIdentifier); // TODO: And these type of additional fetch methods can be methods on the model - the more we break // it up, the easier it is to test and reuse. var comments = await _commentsRepository.GetProjectCommentsAsync(id); await FormatComments(id, projectDetailsAvatarIds, comments); var participants = await _participantsRepository.GetProjectParticipantsAsync(id); var results = await _resultRepository.GetResultsAsync(id); var user = UserModel.GetAuthenticatedUser(User.Identity); var participant = (user.Email == null) ? null : await _participantsRepository.GetAsync(id, user.Email); var userRole = (user.Email == null) ? null : await _userRolesRepository.GetAsync(user.Email.ToLower()); var isAdmin = (userRole != null) && userRole.Role == StreamsRoles.Admin; var isAuthor = (user.Email != null) && user.Email == project.AuthorId; var participantId = ""; var isParticipant = false; var hasResult = false; if (participant != null) { participantId = user.Email; isParticipant = true; hasResult = results.Any(r => r.ParticipantId == user.Email); } var projectFollowing = (user.Email == null) ? null : await _projectFollowRepository.GetAsync(user.Email, id); var isFollowing = projectFollowing != null; // TODO: As I go through this, wondering if we need a CommentsList model, especially since // comments are probably going to be important to the platform going forwards comments = SortComments(comments); var commenterIsModerator = new Dictionary <string, bool>(); foreach (var comment in comments) { var role = await _userRolesRepository.GetAsync(comment.UserId); var isModerator = role != null && role.Role == StreamsRoles.Admin; commenterIsModerator.Add(comment.Id, isModerator); } // TODO: The votes might also need to be broken out, especially if we want to do // 5-star or numeric scoring var userVotedForResults = new Dictionary <string, bool>(); var resultVotes = await _resultVoteRepository.GetProjectResultVotesAsync(project.Id); foreach (var part in participants) { if (string.IsNullOrEmpty(part.UserIdentifier)) { var profile = await _personalDataService.FindClientsByEmail(part.UserId); if (profile != null) { part.UserIdentifier = profile.Id; await _participantsRepository.UpdateAsync(part); } } projectDetailsAvatarIds.Add(part.UserIdentifier); var participantStreamsId = await _streamsIdRepository.GetOrCreateAsync(part.UserIdentifier); part.StreamsId = participantStreamsId.StreamsId; } foreach (var result in results) { if (string.IsNullOrEmpty(result.ParticipantIdentifier)) { var profile = await _personalDataService.FindClientsByEmail(result.ParticipantId); result.ParticipantIdentifier = profile.Id; await _resultRepository.UpdateAsync(result); } var match = resultVotes.FirstOrDefault(x => x.ParticipantId == result.ParticipantId && x.VoterUserId == user.Email); userVotedForResults.Add(result.ParticipantId, match != null && user.Email != null); var resultStreamsId = await _streamsIdRepository.GetOrCreateAsync(result.ParticipantIdentifier); result.StreamsId = resultStreamsId.StreamsId; } var statusBarPartial = ProjectDetailsStatusBarViewModel.Create(project, participants.Count()); var commentsPartial = new ProjectCommentPartialViewModel { ProjectId = project.Id, UserId = user.Email, Comments = comments, IsAdmin = isAdmin, IsAuthor = isAuthor, CommenterIsModerator = commenterIsModerator, ProjectAuthorId = project.AuthorId }; var participantsPartial = new ProjectParticipantsPartialViewModel { CurrentUserId = user.Email, Participants = participants, Status = project.Status, HasResult = hasResult }; var resultsPartial = new ResultsPartialViewModel { Status = project.Status, Results = results, IsAdmin = isAdmin, SkipVoting = project.SkipVoting, UserVotedForResults = userVotedForResults, SubmissionsDeadline = project.ImplementationDeadline }; var allExperts = await _projectExpertsRepository.GetAllUniqueAsync(); var projectExperts = await _projectExpertsRepository.GetProjectExpertsAsync(id); foreach (var expert in projectExperts) { if (string.IsNullOrEmpty(expert.UserIdentifier) && !string.IsNullOrEmpty(expert.UserId)) { var profile = await _personalDataService.FindClientsByEmail(expert.UserId); if (profile != null) { expert.UserIdentifier = profile.Id; await _projectExpertsRepository.UpdateAsync(expert); } } if (!string.IsNullOrEmpty(expert.UserIdentifier)) { projectDetailsAvatarIds.Add(expert.UserIdentifier); expert.StreamsId = (await _streamsIdRepository.GetOrCreateAsync(expert.UserIdentifier)).StreamsId; } } var avatarsDictionary = await _personalDataService.GetClientAvatarsAsync(projectDetailsAvatarIds); participantsPartial.Avatars = avatarsDictionary.ToDictionary(kvp => kvp.Key, kvp => kvp.Value); commentsPartial.Avatars = avatarsDictionary.ToDictionary(kvp => kvp.Key, kvp => kvp.Value); resultsPartial.Avatars = avatarsDictionary.ToDictionary(kvp => kvp.Key, kvp => kvp.Value); projectExperts = projectExperts.OrderBy(x => x.Priority == 0).ThenBy(x => x.Priority); var authorStreamsId = await _streamsIdRepository.GetOrCreateAsync(project.AuthorIdentifier); var projectViewModel = new ProjectViewModel { Id = project.Id, Name = project.Name, Overview = project.Overview, Description = project.Description, ProjectCategories = projectCategories, Category = project.Category, Status = project.Status, BudgetFirstPlace = project.BudgetFirstPlace, BudgetSecondPlace = project.BudgetSecondPlace, VotesFor = project.VotesFor, VotesAgainst = project.VotesAgainst, Created = project.Created, LastModified = project.LastModified, CompetitionRegistrationDeadline = project.CompetitionRegistrationDeadline, ImplementationDeadline = project.ImplementationDeadline, VotingDeadline = project.VotingDeadline, StatusBarPartial = statusBarPartial, CommentsPartial = commentsPartial, ParticipantsPartial = participantsPartial, ResultsPartial = resultsPartial, AuthorId = project.AuthorId, AuthorFullName = project.AuthorFullName, AuthorIdentifier = project.AuthorIdentifier, ParticipantId = participantId, IsParticipant = isParticipant, IsAdmin = isAdmin, IsFollowing = isFollowing, OtherProjects = await GetOtherProjects(project.Id), ProgrammingResourceName = project.ProgrammingResourceName, ProgrammingResourceLink = project.ProgrammingResourceLink, SkipVoting = project.SkipVoting, SkipRegistration = project.SkipRegistration, ProjectExperts = !projectExperts.Any() ? null : projectExperts, PrizeDescription = project.PrizeDescription, StreamId = project.StreamId, AllStreamProjects = await GetStreamProjects(), CompactStreams = await GetCompactStreams(), NameTag = project.NameTag, AuthorAvatarUrl = avatarsDictionary[project.AuthorIdentifier], AuthorStreamsId = authorStreamsId.StreamsId, Experts = allExperts.Select(ExpertViewModel.Create).ToList(), InfoForKycUsers = project.InfoForKycUsers, DescriptionFooter = project.DescriptionFooter }; if (!string.IsNullOrEmpty(project.Tags)) { projectViewModel.TagsList = JsonConvert.DeserializeObject <List <string> >(project.Tags); var builder = new StringBuilder(); foreach (var tag in projectViewModel.TagsList) { builder.Append(tag).Append(", "); } projectViewModel.Tags = builder.ToString(); } projectViewModel.EditStreamProjects = new EditStreamProjects { ProjectsList = new List <StreamProject>() }; if (!string.IsNullOrEmpty(project.StreamId)) { var stream = await _streamRepository.GetAsync(project.StreamId); projectViewModel.StreamProjects = JsonConvert.DeserializeObject <List <StreamProject> >(stream.Stream); } var fileInfo = await _fileInfoRepository.GetAsync(id); if (fileInfo != null) { var fileInfoViewModel = new ProjectFileInfoViewModel { ContentType = fileInfo.ContentType, FileName = fileInfo.FileName }; projectViewModel.FileInfo = fileInfoViewModel; } if (projectViewModel.Status == Status.Archive) { projectViewModel = await PopulateResultsViewModel(projectViewModel); var winners = await _winnersRepository.GetWinnersAsync(project.Id); projectViewModel.Winners = winners.Select(x => WinnerViewModel.Create(x)).ToList(); } projectViewModel.ProjectUrl = project.Id; return(projectViewModel); }