Skip to content

Conversation

@maximgorbatyuk
Copy link
Member

@maximgorbatyuk maximgorbatyuk commented May 11, 2025

Summary by CodeRabbit

  • New Features

    • Added an "Actions" dropdown on the company admin page, allowing admins to edit company details, recalculate rating (not yet implemented), and view the public company page.
    • Introduced an inline modal form for editing company information directly within the admin interface.
  • Improvements

    • Enhanced the company editing workflow with inline validation and success alerts after updates.
    • Unified request types for creating and editing companies for consistency.
  • Style

    • Updated the header text on the inline replies stats page for clarity.

@coderabbitai
Copy link

coderabbitai bot commented May 11, 2025

Walkthrough

The changes introduce inline editing for company details on the admin company page, including a modal form and an actions dropdown. The company update service is implemented, and request types are unified under CompanyEditRequest. Import paths and types are updated accordingly. Minor UI text changes are also present.

Changes

File(s) Change Summary
src/app/modules/admin/components/companies/companies-admin-page/companies-admin-page.component.ts Updated import paths; removed unused import and changed EditCompanyForm import to shared directory.
src/app/modules/admin/components/companies/company-admin-page/company-admin-page.component.html Added "Actions" dropdown and modal dialog for editing company details; introduced inline editing UI.
src/app/modules/admin/components/companies/company-admin-page/company-admin-page.component.ts Added support for editing company details: new form property, modal open/close, form submission, rating stub.
src/app/modules/admin/components/companies/shared/edit-company-form.ts Changed request type from CompanyCreateRequest to CompanyEditRequest in method signature and import.
src/app/services/companies.service.ts Renamed CompanyCreateRequest to CompanyEditRequest; implemented update method; updated create parameter.
src/app/modules/admin/components/telegram/inline-replies-stats/inline-replies-stats.component.html Changed header text from "Bot usage" to "Bot usage chart".

Sequence Diagram(s)

sequenceDiagram
    participant Admin as Admin User
    participant Page as CompanyAdminPageComponent
    participant Modal as EditCompanyForm Modal
    participant Service as CompaniesService
    participant API as Backend API

    Admin->>Page: Clicks "Actions" dropdown
    Admin->>Page: Selects "Редактировать"
    Page->>Modal: Opens EditCompanyForm with current company data
    Admin->>Modal: Edits and submits form
    Modal->>Page: Calls onEditFormSubmit()
    Page->>Service: update(companyId, editRequest)
    Service->>API: POST /api/companies/{id} with editRequest
    API-->>Service: Success response
    Service-->>Page: Observable completes
    Page->>Modal: Closes modal
    Page->>Page: Reloads company data
    Page->>Admin: Shows success alert
Loading

Poem

A bunny hops in admin land,
With dropdowns, forms, and edits planned.
A modal springs up—fields to fill,
Update the company? Yes, I will!
Service sends a gentle POST,
Success! The bunny toasts a toast.
🐇✨

Tip

⚡️ Faster reviews with caching
  • CodeRabbit now supports caching for code and dependencies, helping speed up reviews. This means quicker feedback, reduced wait times, and a smoother review experience overall. Cached data is encrypted and stored securely. This feature will be automatically enabled for all accounts on May 16th. To opt out, configure Review - Disable Cache at either the organization or repository level. If you prefer to disable all data retention across your organization, simply turn off the Data Retention setting under your Organization Settings.

Enjoy the performance boost—your workflow just got faster.

✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@maximgorbatyuk
Copy link
Member Author

Backend: Techinterview-space/web-api#105

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (2)
src/app/modules/admin/components/companies/company-admin-page/company-admin-page.component.html (1)

248-287: Edit form modal implementation is missing a cancel button

The edit form modal looks good, but consider adding a cancel button next to the save button to provide users with a clear way to discard their changes.

 <div class="mb-3">
   <button class="btn btn-primary" type="submit">Сохранить</button>
+  <button type="button" class="btn btn-secondary ms-2" (click)="onEditModalDlgClose()">Отмена</button>
 </div>
src/app/modules/admin/components/companies/company-admin-page/company-admin-page.component.ts (1)

72-90: Form submission looks good but consider refactoring data loading

The form submission logic is well-structured with proper validation checks. However, calling ngOnInit() directly to refresh data is not a typical Angular pattern.

Consider extracting the data loading logic to a separate method that can be called from both ngOnInit() and after form submission:

onEditFormSubmit(): void {
  if (this.editForm == null || this.company == null) {
    return;
  }

  const editRequest = this.editForm.editRequestOrNull();
  if (editRequest == null) {
    return;
  }

  this.service
    .update(this.company.id, editRequest)
    .pipe(untilDestroyed(this))
    .subscribe(() => {
      this.alertService.success("Компания была обновлена");
      this.editForm = null;
-     this.ngOnInit();
+     this.loadCompanyData();
    });
}

+ private loadCompanyData(): void {
+   this.activateRoute
+     .getParam("id")
+     .pipe(untilDestroyed(this))
+     .subscribe((id) => {
+       this.service
+         .byId(id!)
+         .pipe(untilDestroyed(this))
+         .subscribe((i) => {
+           this.company = i;
+           this.company!.description = this.company!.description?.replace(
+             /\n/g,
+             "<br />",
+           );
+
+           this.company!.reviews.forEach((r) => {
+             r.pros = r.pros?.replace(/\n/g, "<br />");
+             r.cons = r.cons?.replace(/\n/g, "<br />");
+           });
+
+           this.title.setTitle(`Компания ${this.company!.name}`);
+         });
+     });
+ }

Then update ngOnInit() to call this method:

ngOnInit(): void {
-  this.activateRoute
-    .getParam("id")
-    .pipe(untilDestroyed(this))
-    .subscribe((id) => {
-      this.service
-        .byId(id!)
-        .pipe(untilDestroyed(this))
-        .subscribe((i) => {
-          this.company = i;
-          this.company!.description = this.company!.description?.replace(
-            /\n/g,
-            "<br />",
-          );
-
-          this.company!.reviews.forEach((r) => {
-            r.pros = r.pros?.replace(/\n/g, "<br />");
-            r.cons = r.cons?.replace(/\n/g, "<br />");
-          });
-
-          this.title.setTitle(`Компания ${this.company!.name}`);
-        });
-    });
+  this.loadCompanyData();
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6cd4971 and e18dbc6.

📒 Files selected for processing (6)
  • src/app/modules/admin/components/companies/companies-admin-page/companies-admin-page.component.ts (1 hunks)
  • src/app/modules/admin/components/companies/company-admin-page/company-admin-page.component.html (2 hunks)
  • src/app/modules/admin/components/companies/company-admin-page/company-admin-page.component.ts (3 hunks)
  • src/app/modules/admin/components/companies/shared/edit-company-form.ts (2 hunks)
  • src/app/modules/admin/components/telegram/inline-replies-stats/inline-replies-stats.component.html (1 hunks)
  • src/app/services/companies.service.ts (2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
src/app/modules/admin/components/companies/shared/edit-company-form.ts (1)
src/app/services/companies.service.ts (1)
  • CompanyEditRequest (17-22)
src/app/modules/admin/components/companies/company-admin-page/company-admin-page.component.ts (1)
src/app/modules/admin/components/companies/shared/edit-company-form.ts (1)
  • EditCompanyForm (5-42)
🔇 Additional comments (11)
src/app/modules/admin/components/telegram/inline-replies-stats/inline-replies-stats.component.html (1)

1-1: Updated header text for clarity.

The header has been changed from “Использование бота” to “График использования бота” to better convey that this view displays a usage chart.

src/app/modules/admin/components/companies/companies-admin-page/companies-admin-page.component.ts (2)

4-4: Import optimization looks good

Replaced the unused PageParams import with the more specific defaultPageParams that's actually used in the code.


9-9: Path update for shared component is correct

The import path for EditCompanyForm has been properly updated to point to the shared location.

src/app/modules/admin/components/companies/shared/edit-company-form.ts (2)

3-3: Interface import update is correct

Updated import to use the renamed CompanyEditRequest interface.


23-23: Return type update is consistent

Updated return type to match the renamed interface CompanyEditRequest.

src/app/services/companies.service.ts (2)

17-22: Interface renaming is a good practice

Renaming CompanyCreateRequest to CompanyEditRequest unifies the request type for both create and update operations, making the code more consistent.


53-53: Parameter type update is consistent

The parameter type has been correctly updated to use the renamed interface.

src/app/modules/admin/components/companies/company-admin-page/company-admin-page.component.ts (4)

92-94: Implement or hide unfinished functionality

The recalculateRating() method is a stub that throws an error. This suggests there's a UI element that triggers this method, which would result in an error for users.

Please verify that this method is not accessible via the UI, or implement the functionality properly. If this feature is planned for a future update, consider either:

  1. Implementing a placeholder that shows a "Coming soon" message to users
  2. Disabling the UI element that triggers this method
  3. Hiding the UI element completely until the functionality is implemented
recalculateRating(): void {
-  throw new Error("Not implemented");
+  this.alertService.info("Функция пересчета рейтинга будет доступна в ближайшем обновлении");
}

11-11: LGTM! Proper import for EditCompanyForm.

The import statement for the EditCompanyForm is correct and follows the project's relative path convention.


22-22: LGTM! Property is properly typed as nullable.

The editForm property is correctly typed as nullable EditCompanyForm | null with proper initialization to null.


68-70: LGTM! Clear method for closing modal.

The onEditModalDlgClose() method correctly handles clearing the form reference when the modal is closed.

Comment on lines +7 to +45
<div class="d-flex justify-content-end">
<div class="btn-group" role="group">
<button
type="button"
class="btn btn-outline-dark dropdown-toggle"
data-bs-toggle="dropdown"
aria-expanded="false"
>
Действия
</button>
<ul class="dropdown-menu">
<li>
<button
type="button"
class="dropdown-item"
(click)="openEditForm()"
>
Редактировать
</button>
</li>
<li>
<button
type="button"
class="dropdown-item"
(click)="recalculateRating()"
>
Пересчитать рейтинг
</button>
</li>
<li>
<a
routerLink="/companies/{{ company.id }}"
class="dropdown-item"
>Публичная страница</a
>
</li>
</ul>
</div>
</div>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Actions dropdown menu is well structured

The dropdown menu provides good access to company actions. However, I have concerns about the recalculate rating functionality.


🏁 Script executed:

#!/bin/bash
# Check if recalculateRating() is implemented properly or throws a not implemented error
rg -A 3 "recalculateRating\(\)" --type ts

Length of output: 527


Implement or remove the “Пересчитать рейтинг” action

The recalculateRating() method currently throws a Not implemented error, so clicking “Пересчитать рейтинг” will break the UI. Please implement the actual rating–recalculation logic or disable/remove this menu item until it’s ready.

Affected location:

  • src/app/modules/admin/components/companies/company-admin-page/company-admin-page.component.ts
    recalculateRating(): void {
      throw new Error("Not implemented");
    }

Suggested fix (example):

-recalculateRating(): void {
-  throw new Error("Not implemented");
-}
+recalculateRating(): void {
+  // TODO: replace with real implementation, e.g.:
+  this.companyService.recalculateRating(this.company.id)
+    .subscribe(updated => (this.company = updated));
+}

Comment on lines +49 to 51
update(id: string, model: CompanyEditRequest): Observable<void> {
return this.api.post(this.apiUrl + id, model);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Consider using PUT instead of POST for updates

While the implementation works, using POST for updates deviates from RESTful conventions. Consider using PUT or PATCH which are more semantically correct for update operations.

  update(id: string, model: CompanyEditRequest): Observable<void> {
-   return this.api.post(this.apiUrl + id, model);
+   return this.api.put(this.apiUrl + id, model);
  }

🏁 Script executed:

#!/bin/bash
# Check if ApiService supports PUT requests
rg -A 1 "put\(" --type ts src/app/services/api.service.ts

Length of output: 59


To ensure whether ApiService actually exposes a put (or patch) method, let’s locate its definition and list supported HTTP verbs:


🏁 Script executed:

#!/bin/bash
# Locate the ApiService file
API_FILE=$(fd --type f 'api.service.ts' | head -n 1)
echo "ApiService file: $API_FILE"

# List any HTTP method wrappers in ApiService
grep -E 'post|get|put|patch' -n "$API_FILE" || echo "No HTTP methods found matching post|get|put|patch"

Length of output: 670


Use HTTP PUT for update operations

The ApiService already exposes a put method (see src/app/services/api.service.ts:40–41), so switching to PUT will align with RESTful conventions for full updates.

• File: src/app/services/companies.service.ts
• Lines: 49–51

  update(id: string, model: CompanyEditRequest): Observable<void> {
-   return this.api.post(this.apiUrl + id, model);
+   return this.api.put(this.apiUrl + id, model);
  }

If you ever need partial updates, you can similarly use this.api.patch(...).

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
update(id: string, model: CompanyEditRequest): Observable<void> {
return this.api.post(this.apiUrl + id, model);
}
update(id: string, model: CompanyEditRequest): Observable<void> {
return this.api.put(this.apiUrl + id, model);
}

Comment on lines +64 to +66
openEditForm(): void {
this.editForm = new EditCompanyForm(this.company);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add null check before creating form

The openEditForm() method should check if this.company is null before creating the form to prevent potential runtime errors.

openEditForm(): void {
+  if (this.company === null) {
+    return;
+  }
  this.editForm = new EditCompanyForm(this.company);
}

@maximgorbatyuk maximgorbatyuk merged commit 1b50726 into main May 11, 2025
1 check failed
@maximgorbatyuk maximgorbatyuk deleted the company-update branch May 11, 2025 14:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants