Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release v.1.4.0-beta #455

Merged
merged 83 commits into from
Jun 7, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
83 commits
Select commit Hold shift + click to select a range
526dbc1
Added route in project controller for retreiving autocompleted projec…
Mar 22, 2021
e7e1172
merge with develop. Resolved conflicts and added Postman tests for au…
Apr 14, 2021
cb91a04
created Postman tests for autocomplete search project suggestions
Apr 14, 2021
8747f73
removed unnecessary lines which broke the unit tests
Apr 14, 2021
199e43f
refactored Postman autocomplete tests
Apr 14, 2021
06832a0
Merge branch 'develop' into feature/361-searchfuntionality
Apr 26, 2021
e43993d
merge develop
Apr 26, 2021
f3aca16
Added missing XML summaries to endpoint and removed unnecessary autho…
Apr 26, 2021
397d36a
refactor order of Elastic tests
Apr 28, 2021
5b5693a
fixed warning in ElasticSynchronizer background services
Apr 28, 2021
4394bff
refactored requested changes
Apr 29, 2021
71fae8c
refactored Postman collection after refactoring the endpoint
Apr 29, 2021
c4967c0
Resolved categories migration conflict
RubenFricke Apr 30, 2021
a971bd3
Revert "Resolved categories migration conflict"
RubenFricke Apr 30, 2021
4513c6c
Resolved migration conflict
RubenFricke Apr 30, 2021
ccc0610
Added highlight image and updated resources
RubenFricke Apr 30, 2021
20ceeea
Removed project id form HighlightResourceResult and included it in Pr…
RubenFricke May 1, 2021
e79b03f
Added Image Id property in Highlight model
RubenFricke May 1, 2021
d449236
Updated ImageId to nullable int in HighlightResource
RubenFricke May 1, 2021
45e8db2
Added checks on existence of Project and File & returned whole object…
RubenFricke May 1, 2021
058c8c5
Added extra existence checks for the update endpoint for highlights
RubenFricke May 1, 2021
c871790
Update CHANGELOG.md
RubenFricke May 1, 2021
00c9a44
Converted project id check to inner id in project check
RubenFricke May 1, 2021
69b6f55
Endpoint logic catches errors now
May 4, 2021
8f49bd2
Merge pull request #435 from DigitalExcellence/master
niraymak May 5, 2021
b6b4560
Made the get all projects function better
TimSnoek123 May 6, 2021
b63ed6f
Update changelog
TimSnoek123 May 6, 2021
e05788d
Merge branch 'develop' into feature/361-searchfuntionality
niraymak May 11, 2021
e837cb7
autocomplete now throws problemdetails which the frontend can show
niraymak May 15, 2021
bfc67b5
Merge pull request #437 from DigitalExcellence/bug/436-get-all-projec…
TimSnoek123 May 18, 2021
34f41a8
updated changelog, controller now more specific error when ElasticSea…
niraymak May 19, 2021
109179d
updated summaries for swagger documentation
niraymak May 19, 2021
87d82c8
updated license from trial to basic
niraymak May 19, 2021
b03e324
Now doesn't get description anymore
TimSnoek123 May 19, 2021
31d2676
Updated changelog
TimSnoek123 May 19, 2021
f652594
Merge pull request #433 from DigitalExcellence/feature/431-add-images…
RubenFricke May 19, 2021
49b54a2
Merge branch 'develop' into feature/361-searchfuntionality
niraymak May 19, 2021
0fb0e85
Added basic multiple image uploader for a project
RubenFricke May 20, 2021
838d848
Update CHANGELOG.md
RubenFricke May 24, 2021
73398c0
Merge pull request #439 from DigitalExcellence/bugfix/436-dont-get-de…
niraymak May 26, 2021
3705b77
Merge branch 'develop' into feature/361-searchfuntionality
niraymak May 26, 2021
7bb4569
added summaries for readability
May 27, 2021
ef0a544
updated max_gram to 25 instead of 10.
niraymak May 28, 2021
78279a1
Update recourses and models
waltersajtos May 28, 2021
bf1b641
Make GET category endpoints public
waltersajtos May 28, 2021
9d0c122
Update getProject endpoints to include categories
waltersajtos May 28, 2021
2cb752d
Update project service and repository to filter for categories
waltersajtos May 28, 2021
2bfd593
Add extra null check on skipCount
waltersajtos May 31, 2021
fc02178
Fix tests
waltersajtos May 31, 2021
f383904
Update seed
waltersajtos Jun 1, 2021
b26321a
added empty list to Project Ids
Jun 1, 2021
f971e0c
Fix entity framework select
waltersajtos Jun 1, 2021
b120d17
Added unique GUIDs
Jun 1, 2021
4dc2515
Update seeding
waltersajtos Jun 1, 2021
06b8d15
Fix category Id selection in linq query
waltersajtos Jun 1, 2021
f1460fa
When no similar users are found, an empty array is now returned inste…
niraymak Jun 1, 2021
cb9f183
Consistent model naming
waltersajtos Jun 1, 2021
1b30e35
Merge remote-tracking branch 'origin/feature/430-add-images-to-projec…
waltersajtos Jun 1, 2021
15057f2
Edited ProducesResponseType annotation. Empty array of ProjectResourc…
niraymak Jun 1, 2021
ae474d7
Merge pull request #445 from DigitalExcellence/feature/430-add-images…
macfleury-2000 Jun 2, 2021
d66f34f
Changed gitignore
Jun 2, 2021
aad2f74
Gitignore
Jun 2, 2021
0bb967e
Merge pull request #423 from DigitalExcellence/feature/361-searchfunt…
RubenFricke Jun 2, 2021
5394e88
Updated appsettings
Jun 2, 2021
ba84d26
Updated git ignore
Jun 2, 2021
5238444
Updated git ignore
Jun 2, 2021
6814f6a
Merge pull request #445 from DigitalExcellence/feature/430-add-images…
macfleury-2000 Jun 2, 2021
3405ea7
Performance testing workflow
BluRRayS Jun 2, 2021
fe278d0
updated Mock method so it will return mocked data with any amount of …
niraymak Jun 2, 2021
e106b89
Merge pull request #451 from DigitalExcellence/BluRRayS-patch-1
BluRRayS Jun 2, 2021
e412370
Update API/Resources/ProjectFilterParamsResource.cs
RubenFricke Jun 2, 2021
161c671
Merge branch 'develop' into feature/444-filter-categories
niraymak Jun 2, 2021
d02b3f8
added summaries to ProjectFilterParamsResource
niraymak Jun 3, 2021
67aa539
Merge branch 'feature/444-filter-categories' of https://github.com/Di…
niraymak Jun 3, 2021
c2dba68
fixed merge error
niraymak Jun 3, 2021
69a4429
update Postman tests after permissions and field name changed
niraymak Jun 3, 2021
73564eb
Seed categories in production
RubenFricke Jun 4, 2021
ae8babd
Added concept category
RubenFricke Jun 4, 2021
dc77555
update changelog
niraymak Jun 4, 2021
3571fbd
Merge pull request #449 from DigitalExcellence/feature/444-filter-cat…
RubenFricke Jun 4, 2021
8e3c72b
updated version numbers for release.
niraymak Jun 7, 2021
9067baa
removed unsucceeding performance testing workflow
niraymak Jun 7, 2021
249dc0f
updated production and staging docker-compose to fix elasticsearch co…
niraymak Jun 7, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -338,4 +338,4 @@ IdentityServer/tempkey.rsa
!/API/Uploads/Images/.gitkeep

###
rabbitmq/data/
rabbitmq/data/
2 changes: 1 addition & 1 deletion API/01_API.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<DocumentationFile>.\API.xml</DocumentationFile>
<Company>Digital Excellence Fontys</Company>
<LangVersion>8</LangVersion>
<Version>1.3.0-beta</Version>
<Version>1.4.0-beta</Version>
</PropertyGroup>

<ItemGroup>
Expand Down
3 changes: 3 additions & 0 deletions API/Configuration/MappingProfile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ public class MappingProfile : Profile
/// </summary>
public MappingProfile()
{
CreateMap<Project, AutocompleteProjectResourceResult>();
CreateMap<AutocompleteProjectResourceResult, Project>();

CreateMap<ProjectLike, UserProjectLikeResourceResult>()
.ForMember(source => source.Id,
option => option
Expand Down
2 changes: 0 additions & 2 deletions API/Controllers/CategoryController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ public CategoryController(ICategoryService categoryService, IProjectCategoryServ
/// <returns>This method returns a list of category resource results.</returns>
/// <response code="200">This endpoint returns a list of categories.</response>
[HttpGet]
[Authorize(Policy = nameof(Scopes.CategoryRead))]
[ProducesResponseType(typeof(IEnumerable<CategoryResourceResult>), (int) HttpStatusCode.OK)]
public async Task<IActionResult> GetAllCategories()
{
Expand All @@ -64,7 +63,6 @@ public async Task<IActionResult> GetAllCategories()
/// <response code="400">The 400 Bad Request status code is returned when the specified category id is invalid.</response>
/// <response code="404">The 404 Not Found status code is returned when no category is found with the specified category id.</response>
[HttpGet("{categoryId}")]
[Authorize(Policy = nameof(Scopes.CategoryRead))]
[ProducesResponseType(typeof(CategoryResourceResult), (int) HttpStatusCode.OK)]
[ProducesResponseType(typeof(ProblemDetails), (int) HttpStatusCode.BadRequest)]
[ProducesResponseType(typeof(ProblemDetails), (int) HttpStatusCode.NotFound)]
Expand Down
98 changes: 93 additions & 5 deletions API/Controllers/HighlightController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
using Models.Defaults;
using Serilog;
using Services.Services;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
Expand All @@ -43,16 +44,22 @@ public class HighlightController : ControllerBase

private readonly IHighlightService highlightService;
private readonly IMapper mapper;
private readonly IFileService fileService;
private readonly IProjectService projectService;

/// <summary>
/// Initializes a new instance of the <see cref="HighlightController" /> class
/// </summary>
/// <param name="highlightService">The highlight service which is used to communicate with the logic layer.</param>
/// <param name="mapper">The mapper which is used to convert the resources to the models to resource results.</param>
public HighlightController(IHighlightService highlightService, IMapper mapper)
/// <param name="fileService">The file service which is used to communicate with the logic layer.</param>
/// <param name="projectService">The project service which is used to communicate with the logic layer.</param>
public HighlightController(IHighlightService highlightService, IMapper mapper, IFileService fileService, IProjectService projectService)
{
this.highlightService = highlightService;
this.mapper = mapper;
this.fileService = fileService;
this.projectService = projectService;
}

/// <summary>
Expand Down Expand Up @@ -165,7 +172,8 @@ public async Task<IActionResult> GetHighlightsByProjectId(int projectId)
[Authorize(Policy = nameof(Defaults.Scopes.HighlightWrite))]
[ProducesResponseType(typeof(HighlightResourceResult), (int) HttpStatusCode.Created)]
[ProducesResponseType(typeof(ProblemDetails), (int) HttpStatusCode.BadRequest)]
public IActionResult CreateHighlight(HighlightResource highlightResource)
[ProducesResponseType(typeof(ProblemDetails), (int) HttpStatusCode.NotFound)]
public async Task<IActionResult> CreateHighlight(HighlightResource highlightResource)
{
if(highlightResource == null)
{
Expand All @@ -179,6 +187,38 @@ public IActionResult CreateHighlight(HighlightResource highlightResource)
}

Highlight highlight = mapper.Map<HighlightResource, Highlight>(highlightResource);
File file = null;

if(highlightResource.ImageId != null)
{
file = await fileService.FindAsync(highlightResource.ImageId.Value);
if(file == null)
{
ProblemDetails problem = new ProblemDetails
{
Title = "File was not found.",
Detail = "The specified file was not found while creating highlight.",
Instance = "F4AF3D06-DD74-40E0-99BB-8E1183A6A734"
};
return NotFound(problem);
}
}

Project project = await projectService.FindWithUserCollaboratorsAndInstitutionsAsync(highlightResource.ProjectId);

if(project == null)
{
ProblemDetails problem = new ProblemDetails
{
Title = "Project was not found.",
Detail = "The specified project was not found while creating highlight.",
Instance = "A6DBEE27-0363-479B-B099-A467D4B2CF00"
};
return NotFound(problem);
}

highlight.Image = file;
highlight.Project = project;

try
{
Expand Down Expand Up @@ -214,6 +254,7 @@ public IActionResult CreateHighlight(HighlightResource highlightResource)
[Authorize(Policy = nameof(Defaults.Scopes.HighlightWrite))]
[ProducesResponseType(typeof(HighlightResourceResult), (int) HttpStatusCode.OK)]
[ProducesResponseType(typeof(ProblemDetails), (int) HttpStatusCode.NotFound)]
[ProducesResponseType(typeof(ProblemDetails), (int) HttpStatusCode.BadRequest)]
public async Task<IActionResult> UpdateHighlight(int highlightId,
[FromBody] HighlightResource highlightResource)
{
Expand All @@ -231,10 +272,57 @@ public async Task<IActionResult> UpdateHighlight(int highlightId,

mapper.Map(highlightResource, highlight);

highlightService.Update(highlight);
highlightService.Save();
File file = null;

return Ok(mapper.Map<Highlight, HighlightResourceResult>(highlight));
if(highlightResource.ImageId != null)
{
file = await fileService.FindAsync(highlightResource.ImageId.Value);
if(file == null)
{
ProblemDetails problem = new ProblemDetails
{
Title = "File was not found.",
Detail = "The specified file was not found while creating highlight.",
Instance = "412CC9A8-CB2A-4389-9F9C-F8494AB65AE0"
};
return NotFound(problem);
}
}

Project project = await projectService.FindWithUserCollaboratorsAndInstitutionsAsync(highlightResource.ProjectId);

if(project == null)
{
ProblemDetails problem = new ProblemDetails
{
Title = "Project was not found.",
Detail = "The specified project was not found while creating highlight.",
Instance = "B923484E-D562-4F03-A57E-88D02819EBD6"
};
return NotFound(problem);
}

highlight.Image = file;
highlight.Project = project;

try
{
highlightService.Update(highlight);
highlightService.Save();

return Ok(mapper.Map<Highlight, HighlightResourceResult>(highlight));
} catch(DbUpdateException e)
{
Log.Logger.Error(e, "Database exception");

ProblemDetails problem = new ProblemDetails
{
Title = "Failed updating highlight.",
Detail = "Failed updating the highlight to the database.",
Instance = "D9933508-F7B6-44B1-9266-5B040D2EA07D"
};
return BadRequest(problem);
}
}

/// <summary>
Expand Down
96 changes: 78 additions & 18 deletions API/Controllers/ProjectController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
using Microsoft.EntityFrameworkCore;
using Models;
using Models.Defaults;
using Models.Exceptions;
using Serilog;
using Services.Services;
using System;
Expand All @@ -34,7 +35,6 @@
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using File = Models.File;

namespace API.Controllers
{
Expand Down Expand Up @@ -228,17 +228,45 @@ public async Task<IActionResult> GetAllProjects(
{
Results = results.ToArray(),
Count = results.Count(),
TotalCount =
await projectService.ProjectsCount(projectFilterParams),
TotalCount = await projectService.ProjectsCount(projectFilterParams),
Page = projectFilterParams.Page,
TotalPages =
await projectService.GetProjectsTotalPages(
projectFilterParams)
TotalPages = await projectService.GetProjectsTotalPages(projectFilterParams)
};

return Ok(resultsResource);
}

/// <summary>
/// This method returns suggestions while searching for projects
/// </summary>
/// <param name="query"></param>
/// <returns>This method returns a list of autocomplete project resources.</returns>
/// <response code="200">This endpoint returns a list with suggested projects.</response>
/// <response code="503">A 503 status code is returned when the Elastic Search service is unavailable.</response>
[HttpGet("search/autocomplete")]
[ProducesResponseType(typeof(List<AutocompleteProjectResourceResult>), (int) HttpStatusCode.OK)]
[ProducesResponseType(typeof(ProblemDetails), 503)]
public async Task<IActionResult> GetAutoCompleteProjects([FromQuery(Name ="query")] string query)
{
try
{
List<Project> projects = await projectService.FindProjectsWhereTitleStartsWithQuery(query);
List<AutocompleteProjectResourceResult> autocompleteProjectResourceResults = mapper.Map<List<Project>, List<AutocompleteProjectResourceResult>>(projects);
return Ok(autocompleteProjectResourceResults);
}
catch(ElasticUnavailableException)
{
return StatusCode(503,
new ProblemDetails
{
Title = "Autocomplete results could not be retrieved.",
Detail = "ElasticSearch service unavailable.",
Instance = "26E7C55F-21DE-4A7B-804C-BC0B74597222"
});
}
}


/// <summary>
/// This method is responsible for retrieving a single project.
/// </summary>
Expand Down Expand Up @@ -340,16 +368,15 @@ await callToActionOptionService.GetCallToActionOptionFromValueAsync(
ProblemDetails problem = new ProblemDetails
{
Title = "Call to action value was not found.",
Detail =
"The specified call to action value was not found while creating the project.",
Detail = "The specified call to action value was not found while creating the project.",
Instance = "40EE82EB-930F-40C8-AE94-0041F7573FE9"
};
return BadRequest(problem);
}
}

Project project = mapper.Map<ProjectResource, Project>(projectResource);
File file = await fileService.FindAsync(projectResource.FileId);
Models.File file = await fileService.FindAsync(projectResource.FileId);

if(projectResource.FileId != 0 &&
file == null)
Expand All @@ -363,6 +390,23 @@ await callToActionOptionService.GetCallToActionOptionFromValueAsync(
return BadRequest(problem);
}

foreach(int projectResourceImageId in projectResource.ImageIds)
{
Models.File image = await fileService.FindAsync(projectResourceImageId);
if(image == null)
{
ProblemDetails problem = new ProblemDetails
{
Title = "Image was not found.",
Detail = "The specified image was not found while creating project.",
Instance = "B040FAAD-FD22-4C77-822E-C498DFA1A9CB"
};
return BadRequest(problem);
}

project.Images.Add(image);
}

project.ProjectIcon = file;
project.User = await HttpContext.GetContextUser(userService)
.ConfigureAwait(false);
Expand All @@ -373,10 +417,10 @@ await callToActionOptionService.GetCallToActionOptionFromValueAsync(

foreach(ProjectCategoryResource projectCategoryResource in projectCategoryResources)
{
ProjectCategory alreadyExcProjectCategory = await projectCategoryService.GetProjectCategory(project.Id, projectCategoryResource.CategoryId);
ProjectCategory alreadyExcProjectCategory = await projectCategoryService.GetProjectCategory(project.Id, projectCategoryResource.Id);
if(alreadyExcProjectCategory == null)
{
Category category = await categoryService.FindAsync(projectCategoryResource.CategoryId);
Category category = await categoryService.FindAsync(projectCategoryResource.Id);

if(category == null)
{
Expand Down Expand Up @@ -491,8 +535,7 @@ await callToActionOptionService.GetCallToActionOptionFromValueAsync(
ProblemDetails problem = new ProblemDetails
{
Title = "Call to action value was not found.",
Detail =
"The specified call to action value was not found while creating the project.",
Detail = "The specified call to action value was not found while creating the project.",
Instance = "40EE82EB-930F-40C8-AE94-0041F7573FE9"
};
return BadRequest(problem);
Expand All @@ -511,15 +554,15 @@ await callToActionOptionService.GetCallToActionOptionFromValueAsync(
}

// Upload the new file if there is one
File file = null;
Models.File file = null;
if(projectResource.FileId != 0)
{
if(project.ProjectIconId != 0 &&
project.ProjectIconId != null)
{
if(project.ProjectIconId != projectResource.FileId)
{
File fileToDelete = await fileService.FindAsync(project.ProjectIconId.Value);
Models.File fileToDelete = await fileService.FindAsync(project.ProjectIconId.Value);

// Remove the file from the filesystem
fileUploader.DeleteFileFromDirectory(fileToDelete);
Expand Down Expand Up @@ -550,17 +593,34 @@ await callToActionOptionService.GetCallToActionOptionFromValueAsync(
}
}

foreach(int projectResourceImageId in projectResource.ImageIds)
{
Models.File image = await fileService.FindAsync(projectResourceImageId);
if(image == null)
{
ProblemDetails problem = new ProblemDetails
{
Title = "Image was not found.",
Detail = "The specified image was not found while creating project.",
Instance = "FC816E40-31A6-4187-BEBA-D22F06019F8F"
};
return BadRequest(problem);
}

project.Images.Add(image);
}

await projectCategoryService.ClearProjectCategories(project);
if(projectResource.Categories != null)
{
ICollection<ProjectCategoryResource> projectCategoryResources = projectResource.Categories;

foreach(ProjectCategoryResource projectCategoryResource in projectCategoryResources)
{
ProjectCategory alreadyExcProjectCategory = await projectCategoryService.GetProjectCategory(project.Id, projectCategoryResource.CategoryId);
ProjectCategory alreadyExcProjectCategory = await projectCategoryService.GetProjectCategory(project.Id, projectCategoryResource.Id);
if(alreadyExcProjectCategory == null)
{
Category category = await categoryService.FindAsync(projectCategoryResource.CategoryId);
Category category = await categoryService.FindAsync(projectCategoryResource.Id);

if(category == null)
{
Expand Down Expand Up @@ -639,7 +699,7 @@ public async Task<IActionResult> DeleteProject(int projectId)
if(project.ProjectIconId.HasValue)
{
// We need to delete the old file.
File fileToDelete = await fileService.FindAsync(project.ProjectIconId.Value);
Models.File fileToDelete = await fileService.FindAsync(project.ProjectIconId.Value);
try
{
// Remove the file from the database
Expand Down
Loading