/// <summary> /// Lists Active Reports from context. Each Report must not be Pending or Deleted. Each Report's Industry must not be Deleted. /// /// </summary> /// <param name="sort">The property to sort the Reports by. Can be left null for default sorting by ID.</param> /// <param name="search">Searches the Report List by Name and Summary. Can be left null to display all Reports.</param> /// <param name="author">Filters the Report List by matching the author's Email address.</param> /// <param name="industry">Filters the Report List by Industry.</param> /// <param name="tag">Filters the Report List by Tag.</param> /// <returns>ICollection of Report Models</returns> public async Task <ICollection <ReportModel> > GetReports(string sort, string search, string author, string industry, string tag) { var reports = await _context.Reports .Where(r => !r.IsDeleted) .Where(r => !r.IsPending) .Include(r => r.Industry) .Where(r => !r.Industry.IsDeleted) .Include(r => r.Author) .Include(r => r.Downloads) .Include(r => r.ReportTags) .ThenInclude(rt => rt.Tag) .Select(r => ReportMapper.MapModelFromEntity(r)) .ToListAsync(); //Sort Reports reports = SortReports(sort, reports).ToList(); //Search Reports reports = SearchReports(search, reports).ToList(); //Filter Reports if (author != null) { reports = reports.Where(r => r.Author.ToLower().Contains(author.ToLower())).ToList(); } if (industry != null) { reports = reports.Where(r => r.Industry.ToLower().Contains(industry.ToLower())).ToList(); } if (tag != null) { reports = reports.Where(r => string.Join(' ', r.Tags).ToLower().Contains(tag.ToLower())).ToList(); } return(reports); }
/// <summary> /// Gets all the Downloaded Reports for a User. /// </summary> /// <param name="userId">The ID of the target User.</param> /// <param name="search">Searches the Reports by Title and Summary.</param> /// <returns>ICollection of Report Models.</returns> public async Task <ICollection <ReportModel> > GetDownloadedReports(int userId, string search) { var user = await _context.Users.FirstOrDefaultAsync(u => u.Id == userId); ValidateUserExists(user); var reports = await _context.DownloadedReports .Include(ur => ur.Report) .ThenInclude(r => r.Author) .Include(ur => ur.Report) .ThenInclude(r => r.Industry) .Include(ur => ur.Report) .ThenInclude(r => r.ReportTags) .ThenInclude(r => r.Tag) .Include(ur => ur.Report) .ThenInclude(r => r.Downloads) .Where(ur => !ur.Report.IsDeleted) .Where(ur => ur.UserId == userId) .Select(ur => ReportMapper.MapModelFromEntity(ur.Report)) .ToListAsync(); reports = SearchReports(search, reports).ToList(); return(reports); }
/// <summary> /// Updates the properties of an existing Report, then moves it to the Pending list. /// </summary> /// <param name="id">The ID for the target Report.</param> /// <param name="title">The new Title of the Report.</param> /// <param name="summary">The new Summary of the Report.</param> /// <param name="description">The new Description of the Report.</param> /// <param name="imgUrl">The path to the new Image to be displayed for the Report.</param> /// <param name="industry">The new Industry of the Report.</param> /// <param name="tags">The new list of Tags for the Report. New Tags will be created if any do not exist.</param> /// <returns>A Report Model on success. </returns> public async Task <ReportModel> UpdateReport(int id, string title, string summary, string description, string imgUrl, string industry, string tags) { //Throw if report with new Title already exists. if (await _context.Reports.AnyAsync(r => r.Title == title && r.Id != id)) { throw new ArgumentException($"Report with title {title} already exists."); } var report = await _context.Reports .Include(r => r.Industry) .Include(r => r.Author) .Include(r => r.ReportTags) .ThenInclude(rt => rt.Tag) .FirstOrDefaultAsync(r => r.Id == id); //Throw if ID is invalid. ValidateReportExists(report); var reportModel = ReportMapper.MapModelFromInput(title, summary, description, imgUrl, null, industry, tags); //Map Title if (title != null && title != string.Empty) { report.Title = reportModel.Title; } //Map Summary if (summary != null && summary != string.Empty) { report.Summary = reportModel.Summary; } //Map Description if (description != null && description != string.Empty) { report.Description = reportModel.Description; } //Map Image if (imgUrl != null && imgUrl != string.Empty) { report.ImgUrl = reportModel.ImgUrl; } //Map Industry report.Industry = await _context.Industries.FirstOrDefaultAsync(i => i.Name == reportModel.Industry); //Set ModifiedOn report.ModifiedOn = DateTime.UtcNow; report.ReportTags.Clear(); //Set Pending report.IsPending = true; await _context.SaveChangesAsync(); //Map Tags, Add new Tags to Context if tags are not found. await AddTagsToReport(report, reportModel.Tags); await _context.SaveChangesAsync(); //Return Report Model reportModel = ReportMapper.MapModelFromEntity(report); return(reportModel); }
/// <summary> /// Gets a report from the context by its ID. /// </summary> /// <param name="id">The ID for the target Report.</param> /// <returns>On success - a Report Model. Throws ArgumentNullException if ID is invalid.</returns> public async Task <ReportModel> GetReport(int id) { var report = await _context.Reports .Include(r => r.Industry) .Include(r => r.Author) .Include(r => r.ReportTags) .ThenInclude(rt => rt.Tag) .FirstOrDefaultAsync(r => r.Id == id); ValidateReportExists(report); var reportDTO = ReportMapper.MapModelFromEntity(report); return(reportDTO); }
/// <summary> /// Lists the 4 Most Downloaded Reports in the context. /// </summary> /// <returns>ICollection of Report Models</returns> public async Task <ICollection <ReportModel> > GetMostDownloadedReports() { var reports = await _context.Reports .Where(r => !r.IsDeleted) .Where(r => !r.IsPending) .Include(r => r.Industry) .Include(r => r.Author) .Include(r => r.Downloads) .Include(r => r.ReportTags) .ThenInclude(rt => rt.Tag) .OrderByDescending(r => r.Downloads.Count) .Take(4) .Select(r => ReportMapper.MapModelFromEntity(r)) .ToListAsync(); return(reports); }
/// <summary> /// Lists all Pending Reports /// </summary> /// <param name="sort">The property to sort the Reports by. Can be left null for default sorting by ID.</param> /// <param name="search">Searches the Report List by Name and Summary. Can be left null to display all Reports.</param> /// <returns>ICollection of Report Models</returns> public async Task <ICollection <ReportModel> > GetPendingReports(string sort, string search) { var reports = await _context.Reports .Where(r => r.IsPending) .Include(r => r.Industry) .Include(r => r.Author) .Include(r => r.ReportTags) .ThenInclude(rt => rt.Tag) .Select(r => ReportMapper.MapModelFromEntity(r)) .ToListAsync(); reports = SortReports(sort, reports).ToList(); reports = SearchReports(search, reports).ToList(); return(reports); }
/// <summary> /// Creates a new Report from given Strings and places it in Pending. /// </summary> /// <param name="title">The title of the new Report. Between 5 and 100 characters.</param> /// <param name="summary">The summary of the new Report. Between 5 and 300 characters.</param> /// <param name="description">The description of the new Report. Between 5 and 5000 characters.</param> /// <param name="author">The author of the new Report. Automatically generated from Identity and the logged in User.</param> /// <param name="imgUrl">The URL for the report's image, which appears on the report's card.</param> /// <param name="industry">The Industry under which the new Report will be classified. Has to match an existing Industry in the context.</param> /// <param name="tags">The Tags to be added to the new Report. If a tag does not exist, it will be created automatically.</param> /// <returns>On success - A Report Model, mapped from the new Report. If the Report already exists - Throws Argument Exception</returns> public async Task <ReportModel> CreateReport(string title, string summary, string description, string author, string imgUrl, string industry, string tags) { var reportModel = ReportMapper.MapModelFromInput(title, summary, description, imgUrl, author, industry, tags); // Throw if Report with this title exists. if (await _context.Reports .Include(r => r.Author) .Include(r => r.Industry) .Include(r => r.ReportTags) .AnyAsync(r => r.Title == title)) { throw new ArgumentException($"Report with title {title} already exists."); } //Create Report var report = new Report() { Title = reportModel.Title, Description = reportModel.Description, Summary = reportModel.Summary, ImgUrl = reportModel.ImgUrl, CreatedOn = DateTime.UtcNow }; await _context.Reports.AddAsync(report); //Map Author, Industry, set Pending report.AuthorId = _context.Users.FirstOrDefault(u => u.NormalizedEmail == reportModel.Author.ToUpper()).Id; report.IndustryId = _context.Industries.FirstOrDefault(i => i.Name.ToUpper() == reportModel.Industry.ToUpper()).Id; report.IsPending = true; await _context.SaveChangesAsync(); //Map Tags, Create new Tags if any do not exist. await AddTagsToReport(report, reportModel.Tags); await _context.SaveChangesAsync(); //Return Report Model reportModel = ReportMapper.MapModelFromEntity(report); return(reportModel); }