Skip to content

Commit

Permalink
Merge branch 'bug/7682/fix-management-page' of https://github.com/ita…
Browse files Browse the repository at this point in the history
…-social-projects/GreenCity into bug/7682/fix-management-page
  • Loading branch information
VasylyshynDmytro committed Jan 10, 2025
2 parents 3878530 + bdec15a commit 7b9c932
Show file tree
Hide file tree
Showing 103 changed files with 5,150 additions and 4,229 deletions.
128 changes: 128 additions & 0 deletions .coderabbit.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
language: en-US
tone_instructions: 'Set the tone of reviews to be professional, constructive, and specific. Offer clear suggestions, encourage collaboration, and acknowledge good practices. Avoid overly critical language; use examples to explain feedback and promote learning.'
early_access: false
enable_free_tier: true
reviews:
profile: chill
request_changes_workflow: false
high_level_summary: true
high_level_summary_placeholder: '@coderabbitai summary'
auto_title_placeholder: '@coderabbitai'
auto_title_instructions: ''
review_status: true
commit_status: true
collapse_walkthrough: false
changed_files_summary: true
sequence_diagrams: true
assess_linked_issues: true
related_issues: true
related_prs: true
suggested_labels: true
auto_apply_labels: false
suggested_reviewers: true
poem: true # Don't remove 'poem:true'—it keeps things nice and poetic.
path_filters:
- '!**/target/**'
- '!**/.git/**'
- '!**/*.mod'
- '!**/*.sum'
- '!**/node_modules/**'
- '!**/dist/**'
- '!**/build/**'
- '!**/*.min.js'
- '!**/*.min.css'
path_instructions:
- path: /**/src/main/**/*.java
instructions: >-
naming:CamelCase;
principles:{single_responsibility,small_methods,no_duplication};
db:{perf_queries,datetime_not_timestamp};
rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos};
dtos:{java_records,no_entities,min_data,single_resp};
di:constructor_injection; kiss:simple_code;
file_handling:os_indep_paths;
practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives};
sql:{param_annotation,uppercase,avoid_subqueries}; java:avoid_star_imports\n
- Review code using Java standards, taking into account the rules defined by `./checkstyle.xml`.
- path: /**/src/test/**/*.java
instructions: >-
test_naming: descriptive; test_size: small_specific; fixed_data: true;
junit5_features: true; assert_use: assertThat; assert_specificity: true;
archunit_use: enforce_package_rules; db_query_count_tests:
track_performance; util_service_factory_pattern: true; avoid_db_access:
true; mock_strategy: static_mocks; context_restart_minimize: true\n
For test code, focus on:
- Correctness of test assertions
- Test coverage of edge cases
- Clear test naming and documentation
- Be more lenient with code style and minor optimisations
- Check for test method naming convention featureTestScenario (https://github.com/ita-social-projects/GreenCity/wiki/Naming-Conventions)
- path: /**/*.js
instructions: |
Review the JavaScript/JQuery code for best practices and potential bugs.
Ensure that the code adheres to modern standards.
Ensure sufficient error handling and logging is present.
Check for common security vulnerabilities such as:
- SQL Injection
- XSS (Cross-Site Scripting)
- CSRF (Cross-Site Request Forgery)
- Insecure dependencies
- Sensitive data exposure
- path: /**/*.html
instructions: |
Review the HTML and Thymeleaf files for correct syntax, structure, and adherence to best practices.
Ensure the following:
- Use semantic HTML elements for better accessibility (e.g., <header>, <main>, <section>, <footer>).
- Validate proper nesting of HTML tags and avoid unclosed elements.
- Check Thymeleaf attributes (e.g., th:text, th:if, th:each) for correctness and clarity.
- Ensure Thymeleaf expressions follow project standards and avoid unnecessary complexity.
- Verify that conditional logic in Thymeleaf is clear, concise, and avoids excessive nesting.
- Ensure proper use of `th:fragment` for reusable components and layout structures.
- Validate that variables and expressions used in Thymeleaf match backend data models.
- Confirm that static assets are referenced using Thymeleaf attributes like `th:src` or `th:href` for consistency.
- Ensure templates are free from inline styles and scripts; prefer external CSS and JS files.
- Check for accessibility best practices:
- Include `alt` attributes for images.
- Use ARIA roles where applicable.
- Validate form inputs for proper labels and placeholders.
- Flag any hardcoded text that should use localization (e.g., `th:text="#{message.key}"`).
- Ensure consistent indentation and formatting for readability.
- Remove unused or commented-out code to maintain clean templates.
Provide detailed feedback with identified issues, recommendations for fixes, and explanations for best practices.
- path: /**/*.css
instructions: |
Review the CSS files for correctness, maintainability, and adherence to best practices.
Ensure the following:
- Use a consistent naming convention, such as BEM (Block-Element-Modifier), for class names.
- Avoid using ID selectors (#id) for styling; prefer class selectors (.class) for better reusability.
- Check for unused CSS selectors and remove them to keep the stylesheet clean.
- Ensure proper grouping of related styles for readability and maintainability.
- Use shorthand properties where applicable (e.g., margin: 0 10px; instead of individual margin properties).
- Validate that colors, fonts, and spacing follow the project's design system or standards.
- Ensure consistent use of units (e.g., avoid mixing `px`, `em`, `rem`, `%`, etc.).
- Check for appropriate use of responsive design techniques (e.g., media queries).
- Ensure proper use of variables (e.g., CSS custom properties or preprocessor variables) for colors, fonts, and sizes.
- Avoid overly specific selectors to prevent CSS bloat and improve maintainability.
- Validate that CSS animations and transitions are smooth and performant.
- Ensure consistent indentation and formatting (e.g., 2 spaces or 4 spaces, depending on project standards).
- Remove !important declarations unless absolutely necessary.
- Minimize inline styles and ensure styles are defined in external stylesheets.
- Check for accessibility considerations, such as sufficient contrast ratios for text and backgrounds.
- Confirm that styles for interactive elements (e.g., buttons, links) include hover, focus, and active states.
Provide detailed feedback with identified issues, recommendations for improvements, and explanations for best practices.
abort_on_close: true
auto_review:
enabled: true
auto_incremental_review: true
drafts: false
base_branches: [ "dev","prod","prod21" ]
chat:
auto_reply: true
knowledge_base:
opt_out: false
learnings:
scope: auto
issues:
scope: auto
pull_requests:
scope: auto
6 changes: 3 additions & 3 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ name: CI/CD GreenCity
concurrency: Testing

on:
# Triggers the workflow on push or pull request events but only for the master branch
# Triggers the workflow on push or pull request events but only for the dev branch
push:
branches: [ master, dev ]
branches: [ dev ]
pull_request:
branches: [ master, dev ]
branches: [ dev ]

env:
repository: greencity
Expand Down
6 changes: 4 additions & 2 deletions core/src/main/java/greencity/config/SecurityConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ public class SecurityConfig {
private static final String NOTIFICATION_ID = "/{notificationId}";
private static final String HABIT_INVITE = "/habit/invite";
private static final String INVITATION_ID = "/{invitationId}";
private static final String COMMIT_INFO = "/commit-info";
private final JwtTool jwtTool;
private final UserService userService;
private final AuthenticationConfiguration authenticationConfiguration;
Expand Down Expand Up @@ -206,7 +207,7 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti
"/habit/assign/confirm/{habitAssignId}",
"/database/backup",
"/database/backupFiles",
"/ai/**")
COMMIT_INFO)
.permitAll()
.requestMatchers(HttpMethod.POST,
SUBSCRIPTIONS,
Expand Down Expand Up @@ -283,7 +284,8 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti
FRIENDS + "/user-data-as-friend/{friendId}",
FRIENDS,
NOTIFICATIONS,
HABIT_ASSIGN_ID + "/friends/habit-duration-info")
HABIT_ASSIGN_ID + "/friends/habit-duration-info",
"/ai/**")
.hasAnyRole(USER, ADMIN, MODERATOR, UBS_EMPLOYEE)
.requestMatchers(HttpMethod.POST,
CATEGORIES,
Expand Down
61 changes: 61 additions & 0 deletions core/src/main/java/greencity/controller/CommitInfoController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package greencity.controller;

import greencity.constant.HttpStatuses;
import greencity.dto.commitinfo.CommitInfoDto;
import greencity.service.CommitInfoService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.ExampleObject;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
* Controller for fetching Git commit information.
*/
@RestController
@RequestMapping("/commit-info")
@RequiredArgsConstructor
public class CommitInfoController {
private final CommitInfoService commitInfoService;

/**
* Endpoint to fetch the latest Git commit hash and date.
*
* @return {@link CommitInfoDto}
*/
@Operation(summary = "Get the latest commit hash and date.")
@ApiResponse(
responseCode = "200",
description = HttpStatuses.OK,
content = @Content(
mediaType = "application/json",
examples = @ExampleObject(
value = """
{
"commitHash": "d6e70c46b39857846f3f13ca9756c39448ab3d6f",
"commitDate": "16/12/2024 10:55:00"
}""")))
@ApiResponse(
responseCode = "404",
description = HttpStatuses.NOT_FOUND,
content = @Content(
mediaType = "application/json",
examples = @ExampleObject(
value = """
{
"timestamp": "2024-12-19T14:42:06.469+00:00",
"status": 404,
"error": "Not Found",
"trace": "greencity.exception.exceptions.ResourceNotFoundException",
"message": "Git repository not initialized. Commit info is unavailable.",
"path": "/commit-info"
}""")))
@GetMapping
public ResponseEntity<CommitInfoDto> getCommitInfo() {
return ResponseEntity.ok(commitInfoService.getLatestCommitInfo());
}
}
23 changes: 17 additions & 6 deletions core/src/main/java/greencity/controller/FriendController.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import org.springframework.data.web.PageableDefault;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.lang.Nullable;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
Expand Down Expand Up @@ -231,10 +230,16 @@ public ResponseEntity<PageableDto<UserFriendDto>> findUserFriendsByUserIAndShowF
public ResponseEntity<PageableDto<UserFriendDto>> findAllUsersExceptMainUserAndUsersFriendAndRequestersToMainUser(
@Parameter(hidden = true) @PageableDefault Pageable page,
@Parameter(hidden = true) @CurrentUser UserVO userVO,
@RequestParam(required = false) @Nullable String name) {
@RequestParam(required = false, defaultValue = "") String name,
@RequestParam(required = false, defaultValue = "false") boolean filterByFriendsOfFriends,
@RequestParam(required = false, defaultValue = "false") boolean filterByCity) {
return ResponseEntity
.status(HttpStatus.OK)
.body(friendService.findAllUsersExceptMainUserAndUsersFriendAndRequestersToMainUser(userVO.getId(), name,
.body(friendService.findAllUsersExceptMainUserAndUsersFriendAndRequestersToMainUser(
userVO.getId(),
name,
filterByFriendsOfFriends,
filterByCity,
page));
}

Expand Down Expand Up @@ -284,11 +289,13 @@ public ResponseEntity<PageableDto<UserFriendDto>> findRecommendedFriends(
@GetMapping("/friendRequests")
@ApiPageable
public ResponseEntity<PageableDto<UserFriendDto>> getAllUserFriendsRequests(
@RequestParam(required = false, defaultValue = "") String name,
@RequestParam(required = false, defaultValue = "false") boolean filterByCity,
@Parameter(hidden = true) Pageable page,
@Parameter(hidden = true) @CurrentUser UserVO userVO) {
return ResponseEntity
.status(HttpStatus.OK)
.body(friendService.getAllUserFriendRequests(userVO.getId(), page));
.body(friendService.getAllUserFriendRequests(userVO.getId(), name, filterByCity, page));
}

/**
Expand All @@ -310,12 +317,16 @@ public ResponseEntity<PageableDto<UserFriendDto>> getAllUserFriendsRequests(
@GetMapping
@ApiPageable
public ResponseEntity<PageableDto<UserFriendDto>> findAllFriendsOfUser(
@RequestParam(required = false, defaultValue = "") String name,
@RequestParam(required = false, defaultValue = "false") boolean filterByCity,
@Parameter(hidden = true) Pageable page,
@RequestParam(required = false) @Nullable String name,
@Parameter(hidden = true) @CurrentUser UserVO userVO) {
return ResponseEntity
.status(HttpStatus.OK)
.body(friendService.findAllFriendsOfUser(userVO.getId(), name, page));
.body(friendService.findAllFriendsOfUser(userVO.getId(),
name,
filterByCity,
page));
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package greencity.webcontroller;

import greencity.constant.HttpStatuses;
import greencity.dto.habitstatistic.HabitDateCount;
import greencity.service.HabitStatisticService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import lombok.AllArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.List;
import java.util.Map;

@Controller
@AllArgsConstructor
@RequestMapping("/management/habit/statistics")
public class ManagementHabitStatisticController {
HabitStatisticService habitStatisticService;

@GetMapping
public String getStatisticsPage() {
return "core/management_habit_statistics";
}

/**
* Endpoint to retrieve user interest statistics.
*
* @return ResponseEntity containing user interest statistics.
*/
@Operation(summary = "Retrieve user interest statistics.")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = HttpStatuses.OK),
@ApiResponse(responseCode = "403", description = HttpStatuses.FORBIDDEN)
})
@GetMapping("/interest")
public ResponseEntity<Map<String, Long>> getUserInterestStatistics() {
return ResponseEntity.ok(habitStatisticService.calculateUserInterest());
}

/**
* Endpoint to retrieve habit behavior statistics.
*
* @return ResponseEntity containing habit behavior statistics.
*/
@Operation(summary = "Retrieve statistics of how users behave with habits.")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = HttpStatuses.OK),
@ApiResponse(responseCode = "403", description = HttpStatuses.FORBIDDEN)
})
@GetMapping("/habit-behavior")
public ResponseEntity<Map<String, Long>> getHabitBehaviorStatistics() {
return ResponseEntity.ok(habitStatisticService.calculateHabitBehaviorStatistic());
}

/**
* Endpoint to retrieve user interaction with habits(creation, subscription).
*
* @return ResponseEntity containing habit behavior statistics.
*/
@Operation(summary = "Retrieve statistics of how users interact with habits.")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = HttpStatuses.OK),
@ApiResponse(responseCode = "403", description = HttpStatuses.FORBIDDEN)
})
@GetMapping("/user-interaction")
public ResponseEntity<Map<String, List<HabitDateCount>>> getUserHabitInteractionStatistics(
@RequestParam(defaultValue = "weekly") String range) {
return ResponseEntity.ok(habitStatisticService.calculateInteractions(range));
}
}
4 changes: 3 additions & 1 deletion core/src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,6 @@ spring.messaging.stomp.websocket.allowed-origins=\
http://localhost:4200/, \
http://localhost:4205/*

server.tomcat.relaxed-query-chars=<, >, [, \,, ], ^, `, {, |, }
server.tomcat.relaxed-query-chars=<, >, [, \,, ], ^, `, {, |, }

spring.jackson.time-zone=Europe/Kyiv
Loading

0 comments on commit 7b9c932

Please sign in to comment.