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

feat(MeiliSearch): add MeiliSearch component #133

Merged
merged 9 commits into from
Nov 20, 2024
Merged

Conversation

ArgoZhang
Copy link
Contributor

@ArgoZhang ArgoZhang commented Nov 20, 2024

add MeiliSearch component

Summary of the changes (Less than 80 chars)

Description

fixes #132

Customer Impact

Regression?

  • Yes
  • No

[If yes, specify the version the behavior has regressed from]

Risk

  • High
  • Medium
  • Low

[Justify the selection above]

Verification

  • Manual (required)
  • Automated

Packaging changes reviewed?

  • Yes
  • No
  • N/A

☑️ Self Check before Merge

⚠️ Please check all items below before review. ⚠️

  • Doc is updated/provided or not needed
  • Demo is updated/provided or not needed
  • Merge the latest code from the main branch

Summary by Sourcery

New Features:

  • Introduce a new MeiliSearch component for enhanced search capabilities.

Copy link

sourcery-ai bot commented Nov 20, 2024

Reviewer's Guide by Sourcery

This PR adds a new MeiliSearch component to the BootstrapBlazor library, implementing client-side search functionality using the MeiliSearch search engine. The implementation includes the core component, JavaScript interop, styling, and configuration options.

No diagrams generated as the changes look simple and do not need a visual representation.

File-Level Changes

Change Details Files
Added MeiliSearch component implementation
  • Created MeiliSearchBox Razor component with search UI elements
  • Implemented component parameters and configuration options
  • Added JavaScript module initialization and event handling
  • Integrated MeiliSearch client-side library
MeiliSearchBox.razor
MeiliSearchBox.razor.cs
MeiliSearchBox.razor.js
Added configuration and dependency injection support
  • Created MeiliSearchOptions class for configuration
  • Added service collection extension method for registration
  • Implemented options monitoring for configuration updates
MeiliSearchOptions.cs
Extensions/ServiceCollectionExtensions.cs
Added client-side resources
  • Added MeiliSearch UMD JavaScript library
  • Added component CSS styles
  • Implemented responsive design for mobile and desktop
wwwroot/meilisearch.umd.js
wwwroot/meilisearch.umd.min.js
wwwroot/meilisearch.css

Assessment against linked issues

Issue Objective Addressed Explanation
#132 Add MeiliSearch component to the project

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time. You can also use
    this command to specify where the summary should be inserted.

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@bb-auto bb-auto bot added the enhancement New feature or request label Nov 20, 2024
@bb-auto bb-auto bot added this to the v9.0.0 milestone Nov 20, 2024
@ArgoZhang ArgoZhang merged commit ee2e0ff into master Nov 20, 2024
0 of 2 checks passed
@ArgoZhang ArgoZhang deleted the dev-mailsearch branch November 20, 2024 12:18
Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey @ArgoZhang - I've reviewed your changes and found some issues that need to be addressed.

Blocking issues:

  • Search input should be sanitized before making API calls (link)

Overall Comments:

  • Consider adding XML documentation comments for the public APIs to improve IntelliSense experience
Here's what I looked at during the review
  • 🟡 General issues: 3 issues found
  • 🔴 Security: 1 blocking issue
  • 🟢 Testing: all looks good
  • 🟡 Complexity: 1 issue found
  • 🟢 Documentation: all looks good

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.


resetStatus(search);

new bootstrap.ScrollSpy(search.list, {
Copy link

Choose a reason for hiding this comment

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

issue (bug_risk): The ScrollSpy instance should be properly disposed to prevent memory leaks

Store the ScrollSpy instance in the search object and call dispose() on it in the dispose() method

resetStatus(search);
}
});
const fn = debounce(doSearch);
Copy link

Choose a reason for hiding this comment

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

suggestion: The debounce delay should be configurable to handle different use cases

Consider adding a debounceDelay option to the component's configuration

Suggested change
const fn = debounce(doSearch);
const defaultDelay = 300;
const debounceDelay = options?.debounceDelay ?? defaultDelay;
const fn = debounce(doSearch, debounceDelay);

}

const doSearch = async (search, query) => {
if (query) {
Copy link

Choose a reason for hiding this comment

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

🚨 issue (security): Search input should be sanitized before making API calls

Add input validation and sanitization to prevent potential XSS or injection attacks

const doSearch = async (search, query) => {
if (query) {
search.status.innerHTML = search.searchText;
const client = new MeiliSearch({
Copy link

Choose a reason for hiding this comment

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

issue: Error handling could be more comprehensive for API client initialization

Add specific error handling for network issues, invalid credentials, and other potential API client initialization failures

}
}

const updateList = (search, result) => {
Copy link

Choose a reason for hiding this comment

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

issue (complexity): Consider using template literals for HTML generation instead of manual DOM manipulation

The updateList function's manual DOM manipulation adds unnecessary complexity. Consider simplifying using template literals while maintaining the same functionality:

const updateList = (search, result) => {
    const { menu, list, input, template, blockTemplate } = search;

    const menuHtml = result.hits.map(hit => `
        <a class="search-dialog-menu-item" href="#hit${hit.id}">${hit.menu}</a>
    `).join('');

    const listHtml = result.hits.map(hit => {
        if (hit.title === '') return '';

        const demosHtml = hit.demos ? `
            <ol class="mb-0 mt-2">
                ${hit.demos.map(block => `
                    <li>
                        <a href="${block.url || hit.url}">
                            <h5>${highlight(block.title, result.query)}</h5>
                            <p>${highlight(block.intro, result.query)}</p>
                        </a>
                    </li>
                `).join('')}
            </ol>
        ` : '';

        return `
            <div id="hit${hit.id}" class="search-dialog-item">
                <a href="${hit.url}">
                    <h4>${highlight(hit.title, result.query)}</h4>
                    <p>${highlight(hit.subTitle, result.query)}</p>
                    <span>${hit.demos.length}</span>
                </a>
                ${demosHtml}
            </div>
        `;
    }).join('');

    menu.innerHTML = menuHtml;
    menu.classList.add('show');
    list.innerHTML = listHtml;
    input.focus();

    bootstrap.ScrollSpy.getInstance(list).refresh();
};

This approach:

  • Eliminates manual DOM element creation
  • Reduces nesting and improves readability
  • Maintains all existing functionality
  • Uses a single innerHTML operation per container

};
}
function _callSuper(t, o, e) {
return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e));
Copy link

Choose a reason for hiding this comment

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

issue (code-quality): Don't reassign parameter - o (dont-reassign-parameters)

ExplanationReassigning parameters can lead to unexpected behavior, especially when accessing the arguments object. It can also cause optimization issues, especially in V8.

From the Airbnb JavaScript Style Guide

Comment on lines +326 to +328
function _classCallCheck(a, n) {
if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function");
}
Copy link

Choose a reason for hiding this comment

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

issue (code-quality): Avoid function declarations, favouring function assignment expressions, inside blocks. (avoid-function-declarations-in-blocks)

ExplanationFunction declarations may be hoisted in Javascript, but the behaviour is inconsistent between browsers. Hoisting is generally confusing and should be avoided. Rather than using function declarations inside blocks, you should use function expressions, which create functions in-scope.

return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e));
}
function _classCallCheck(a, n) {
if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function");
Copy link

Choose a reason for hiding this comment

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

suggestion (code-quality): Use block braces for ifs, whiles, etc. (use-braces)

Suggested change
if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function");
if (!(a instanceof n)) {


ExplanationIt is recommended to always use braces and create explicit statement blocks.

Using the allowed syntax to just write a single statement can lead to very confusing
situations, especially where subsequently a developer might add another statement
while forgetting to add the braces (meaning that this wouldn't be included in the condition).

Comment on lines +329 to +335
function _construct(t, e, r) {
if (_isNativeReflectConstruct()) return Reflect.construct.apply(null, arguments);
var o = [null];
o.push.apply(o, e);
var p = new (t.bind.apply(t, o))();
return r && _setPrototypeOf(p, r.prototype), p;
}
Copy link

Choose a reason for hiding this comment

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

issue (code-quality): Avoid function declarations, favouring function assignment expressions, inside blocks. (avoid-function-declarations-in-blocks)

ExplanationFunction declarations may be hoisted in Javascript, but the behaviour is inconsistent between browsers. Hoisting is generally confusing and should be avoided. Rather than using function declarations inside blocks, you should use function expressions, which create functions in-scope.

if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function");
}
function _construct(t, e, r) {
if (_isNativeReflectConstruct()) return Reflect.construct.apply(null, arguments);
Copy link

Choose a reason for hiding this comment

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

suggestion (code-quality): Use block braces for ifs, whiles, etc. (use-braces)

Suggested change
if (_isNativeReflectConstruct()) return Reflect.construct.apply(null, arguments);
if (_isNativeReflectConstruct()) {


ExplanationIt is recommended to always use braces and create explicit statement blocks.

Using the allowed syntax to just write a single statement can lead to very confusing
situations, especially where subsequently a developer might add another statement
while forgetting to add the braces (meaning that this wouldn't be included in the condition).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

feat(MeiliSearch): add MeiliSearch component
1 participant