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: extract public api to the composition class #676

Merged
merged 12 commits into from
Jul 2, 2024
Merged

Conversation

nd0ut
Copy link
Member

@nd0ut nd0ut commented Jun 17, 2024

Description

Checklist

Summary by CodeRabbit

  • New Features
    • Introduced UploaderPublicApi class with new methods for managing file uploads and API access.
  • Bug Fixes
    • Improved error handling by replacing references from block to api across multiple validators.
    • Enhanced control flow and method calls in various components to ensure correct API usage.
  • Refactor
    • Updated method calls to use this.api instead of this for improved modularity and clarity.
    • Removed deprecated methods and added visibility modifiers for better code organization and access control.

Copy link
Contributor

coderabbitai bot commented Jun 17, 2024

Warning

Review failed

The pull request is closed.

Walkthrough

The changes focus on refining various classes and methods related to file uploading and validation in a JavaScript project. Key updates include the introduction of the UploaderPublicApi class for managing file actions, removal of deprecated methods, and enhanced visibility modifiers for methods. The modifications improve the structure, error handling, and accessibility of the code by centralizing functionalities within the UploaderPublicApi class and updating method references accordingly.

Changes

File(s) Change Summary
abstract/ActivityBlock.js Set *modalActive state to false when no activity is present and updated ActivityType typedef.
abstract/Block.js Removed setActivity method, added visibility modifiers to various methods.
abstract/CTX.js Removed *uploadCollection from uploaderBlockCtx function.
abstract/UploaderBlock.js Restructured initialization, added UploaderPublicApi, and removed multiple deprecated imports.
blocks/ExternalSource/ExternalSource.js Updated method calls from this to this.api for addFileFromUrl.
abstract/UploaderPublicApi.js Added methods for file manipulation and flow control.
abstract/ValidationManager.js Switched function parameters to use api from UploaderPublicApi and updated method calls.
blocks/CameraSource/CameraSource.js Updated method calls from this to this.api for addFileFromObject.
blocks/DropArea/DropArea.js Updated method calls to use this.api.
blocks/SourceBtn/SourceBtn.js Changed openSystemDialog calls to use this.api.
blocks/UploadList/UploadList.js Updated method calls to use this.api for initialization, uploading, and finalization processes.
blocks/UrlSource/UrlSource.js Updated method call from this to this.api for addFileFromUrl.
blocks/SimpleBtn/SimpleBtn.js Updated initFlow call to use this.api.
build-svg-sprite.js Appended newline character after trimming string template.
types/exported.d.ts Added export statement for UploaderPublicApi.
utils/validators/collection/validateCollectionUploadError.js, utils/validators/file/... Replaced references to block with api and updated property accesses and function calls.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant App
    participant UploaderPublicApi

    User ->> App: Initiate file upload
    App ->> UploaderPublicApi: addFileFromObject(file)
    UploaderPublicApi ->> App: Return upload status
    App ->> User: Display upload status
Loading
sequenceDiagram
    participant User
    participant App
    participant UploaderPublicApi

    User ->> App: Trigger open system dialog
    App ->> UploaderPublicApi: openSystemDialog(options)
    UploaderPublicApi ->> User: Open file selection dialog
    User ->> UploaderPublicApi: Select file(s)
    UploaderPublicApi ->> App: Return selected files
    App ->> User: Display selected files
Loading

Poem

Changes come, as swift as light,
The code refined, now sleek and bright,
Uploader's tasks are clear and true,
With PublicApi, a fresh new view.
Worries fade, like morning dew,
For bugs are scarce and features woo.
A rabbit's joy, in this code's clue. 🐇✨


Tip

Early access features: disabled

We are currently testing the following features in early access:

  • OpenAI gpt-4o model for code reviews and chat: OpenAI claims that this model is better at understanding and generating code than the previous models. We seek your feedback over the next few weeks before making it generally available.

Note:

  • You can enable or disable early access features from the CodeRabbit UI or by updating the CodeRabbit configuration file.
  • Please join our Discord Community to provide feedback and report issues.
  • OSS projects are currently opted into early access features by default.
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>.
    • 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 generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @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.

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 as 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 resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configration 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.

Base automatically changed from feat/remove-deprecated-api to main June 23, 2024 21:24
@nd0ut nd0ut force-pushed the feat/public-api branch from eb4aeb3 to 6de876f Compare June 24, 2024 17:45
@nd0ut nd0ut requested a review from egordidenko June 24, 2024 17:47
Copy link
Contributor

@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

Outside diff range and nitpick comments (3)
utils/validators/file/validateFileType.js (1)

Line range hint 5-26: Refactor and optimize the validateFileType function.

The function validateFileType has been adapted to use the api object for configuration access and localization, which aligns with the new architecture. However, the logic could be further optimized:

  • DRY Principle: The conditions for checking mimeType and fileName could be combined to reduce redundancy.
  • Error Handling: There is no error thrown or logged when both mime and extension checks fail, which could lead to silent failures in file validation.

Consider refactoring the function to improve readability and error handling.

export const validateFileType = (outputEntry, api) => {
  const { mimeType, name: fileName } = outputEntry;
  const { imgOnly, accept } = api.cfg;
  const allowedFileTypes = mergeFileTypes([...(imgOnly ? IMAGE_ACCEPT_LIST : []), accept]);

  if (!allowedFileTypes.length || !mimeType || !fileName) {
    // Skip validation if conditions are not met
    return;
  }

  const mimeOk = matchMimeType(mimeType, allowedFileTypes);
  const extOk = matchExtension(fileName, allowedFileTypes);

  if (!mimeOk && !extOk) {
    return {
      type: 'FORBIDDEN_FILE_TYPE',
      message: api.l10n('file-type-not-allowed'),
      payload: { entry: outputEntry },
    };
  }
};
utils/validators/file/validateUploadError.js (1)

Line range hint 5-33: Enhance error handling and internal API usage in validateUploadError.

The function validateUploadError utilizes internal APIs and performs comprehensive error checks, which is good for robustness. However, there are a few points to consider:

  • Internal API Usage: The use of a private API (_uploadCollection.read) is flagged with a @ts-expect-error comment, which might indicate a potential design flaw or a need for API adjustment.
  • Error Handling: The function could benefit from more nuanced error handling, especially for unknown errors, to aid in debugging and maintenance.

Consider discussing with the team the possibility of exposing necessary parts of the internal API officially or finding an alternative approach.

abstract/ValidationManager.js (1)

Line range hint 79-110: Ensure correct handling of validation errors and API interactions.

The changes in runCollectionValidators and _runFileValidatorsForEntry reflect the shift to using the api object. It's crucial to ensure that the api methods called (getOutputCollectionState, getOutputItem) are robust and handle errors appropriately. Consider adding more detailed error logging or handling mechanisms to improve fault tolerance and debuggability.

Also applies to: 122-130

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 4fdf9a0 and 6de876f.

Files selected for processing (19)
  • abstract/CTX.js (1 hunks)
  • abstract/UploaderBlock.js (16 hunks)
  • abstract/UploaderPublicApi.js (1 hunks)
  • abstract/ValidationManager.js (5 hunks)
  • blocks/CameraSource/CameraSource.js (1 hunks)
  • blocks/DropArea/DropArea.js (2 hunks)
  • blocks/ExternalSource/ExternalSource.js (1 hunks)
  • blocks/SimpleBtn/SimpleBtn.js (1 hunks)
  • blocks/SourceBtn/SourceBtn.js (2 hunks)
  • blocks/UploadList/UploadList.js (3 hunks)
  • blocks/UrlSource/UrlSource.js (1 hunks)
  • types/test/lr-config.test-d.tsx (1 hunks)
  • types/test/lr-upload-ctx-provider.test-d.tsx (1 hunks)
  • utils/validators/collection/validateCollectionUploadError.js (1 hunks)
  • utils/validators/collection/validateMultiple.js (2 hunks)
  • utils/validators/file/validateFileType.js (2 hunks)
  • utils/validators/file/validateIsImage.js (2 hunks)
  • utils/validators/file/validateMaxSizeLimit.js (1 hunks)
  • utils/validators/file/validateUploadError.js (1 hunks)
Files not reviewed due to errors (1)
  • types/test/lr-upload-ctx-provider.test-d.tsx (no review received)
Additional context used
Biome
abstract/UploaderPublicApi.js

[error] 188-188: Avoid redundant double-negation. (lint/complexity/noExtraBooleanCast)

It is not necessary to use double-negation when a value will already be coerced to a boolean.
Unsafe fix: Remove redundant double-negation

Additional comments not posted (22)
utils/validators/collection/validateCollectionUploadError.js (1)

4-8: Refactor Approved: Updated function to use the new API object.

The refactoring of validateCollectionUploadError to use the api object for retrieving localized messages aligns with the PR's objective to centralize API interactions. This should make the code easier to maintain and test.

utils/validators/file/validateMaxSizeLimit.js (1)

5-11: Refactor Approved: Function now utilizes API object for configuration and localization.

The changes to validateMaxSizeLimit ensure that the function uses the centralized api object for configuration values and localization, which is consistent with the PR's goal of centralizing functionalities. This should enhance maintainability and ensure that configuration management is more streamlined.

utils/validators/file/validateIsImage.js (1)

Line range hint 4-22: Refactor Approved: Enhanced maintainability by using API object.

The refactoring of validateIsImage to utilize the api object for configuration checks and localization aligns with the overarching goal of the PR. This change not only makes the code cleaner but also ensures that all configuration and localization are managed centrally through the api object.

utils/validators/collection/validateMultiple.js (1)

Line range hint 4-28: Refactor Approved: Centralized configuration and localization through API object.

The updates to validateMultiple to use the api object for configuration and localization are well-executed. This change supports the PR's goal of centralizing API interactions, which should simplify future modifications and maintenance of the codebase by having a single point of configuration and localization.

abstract/CTX.js (1)

Line range hint 1-30: Code consistency and documentation improvement in CTX.js.

The file CTX.js provides context factories for different block types. While the implementation is generally sound, there are a few areas that could be improved for better readability and maintainability:

  • Documentation: More detailed JSDoc comments could be helpful, especially for functions like activityBlockCtx and uploaderBlockCtx to explain their purposes and usage more clearly.
  • Code Consistency: The usage of spread operators and new object constructions is consistent. However, ensuring that all functions follow similar patterns and standards would be beneficial.

Consider adding more detailed comments and reviewing the consistency of pattern usage across the project.

types/test/lr-config.test-d.tsx (1)

78-79: Ensure consistency in validator structure and error handling.

The validators maxSize and maxCollection have been updated to use the api object. Ensure all related validators across the project are updated similarly for consistency. Additionally, consider adding error handling or validation inside the validator functions to catch potential issues early.

Also applies to: 83-84

blocks/SourceBtn/SourceBtn.js (1)

42-42: Review the use of api.openSystemDialog for potential side effects.

The method openSystemDialog is now being called with different parameters based on the source type. Ensure that this method properly handles these parameters and that there are no unintended side effects or state changes that could affect the application's stability.

Also applies to: 57-57

Verification successful

Review the use of api.openSystemDialog for potential side effects.

The openSystemDialog method in abstract/UploaderPublicApi.js creates an input element for file selection and handles various configurations based on the provided options. It does not appear to introduce unintended side effects or state changes that could affect the application's stability.

  • The method creates an input element, sets its type to 'file', and configures its attributes based on the options and the instance's configuration.
  • It handles the captureCamera option by setting the capture and accept attributes appropriately.
  • It triggers a click event on the input element and sets up an onchange event handler to manage file selection.

No issues were found in the implementation that would suggest unintended side effects.

Scripts executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify the implementation of `openSystemDialog` to handle parameters correctly.
ast-grep --lang javascript --pattern $'openSystemDialog($_) { $$$ }' ../../abstract/UploaderPublicApi.js

Length of output: 556



Script:

#!/bin/bash
# Description: Verify the implementation of `openSystemDialog` to handle parameters correctly.
ast-grep --lang javascript --pattern 'function openSystemDialog($_) { $$$ }' $(fd UploaderPublicApi.js)

Length of output: 135



Script:

#!/bin/bash
# Description: Locate the definition of `openSystemDialog` function across the codebase.
rg 'function openSystemDialog' --glob '*.js'

Length of output: 46



Script:

#!/bin/bash
# Description: Locate the definition of `openSystemDialog` method within classes or objects across the codebase.
rg 'openSystemDialog\s*\(.*\)\s*\{' --glob '*.js'

Length of output: 116



Script:

#!/bin/bash
# Description: Retrieve the full implementation of the `openSystemDialog` method.
ast-grep --lang javascript --pattern 'openSystemDialog(options = {}) { $$$ }' abstract/UploaderPublicApi.js

Length of output: 570



Script:

#!/bin/bash
# Description: Retrieve the full implementation of the `openSystemDialog` method.
ast-grep --lang javascript --pattern 'openSystemDialog($_) { $$$ }' abstract/UploaderPublicApi.js

Length of output: 550



Script:

#!/bin/bash
# Description: Retrieve the full implementation of the `openSystemDialog` method.
rg -A 20 'openSystemDialog' abstract/UploaderPublicApi.js

Length of output: 1787

blocks/CameraSource/CameraSource.js (1)

174-174: Proper integration of the api object in the CameraSource class.

The use of api.addFileFromObject for adding files captured from the camera is a correct application of the new centralized API handling mechanism. This change ensures that all file operations go through a unified interface, improving maintainability.

blocks/UploadList/UploadList.js (1)

38-38: Consistent use of the api object across UploadList methods.

The modifications to use the api object for initiating flows, managing uploads, and handling completion are correctly implemented. This centralization facilitates better control and modification of upload behaviors from a single point, which is a significant improvement in code architecture.
[APROVED]

Also applies to: 42-42, 46-47, 69-69, 166-166

blocks/ExternalSource/ExternalSource.js (1)

52-52: Effective integration of the api object in handling external sources.

The update to use api.addFileFromUrl for adding files from external sources aligns with the centralized API strategy. This ensures consistency and maintainability in handling files across different sources.

blocks/DropArea/DropArea.js (2)

112-114: Refactor: Use api object for file interactions.

The methods addFileFromUrl and addFileFromObject have been updated to use the api object instead of direct method calls. This change aligns with the centralization of API methods in the UploaderPublicApi class, improving modularity and maintainability.


176-179: Refactor: Use api object for system dialog interactions.

The openSystemDialog method is now called through the api object when the DropArea is clicked or receives a keydown event. This centralizes the control over system dialog interactions, which is a good practice for consistency and potential future enhancements.

abstract/UploaderPublicApi.js (7)

44-52: Refactor: Implement addFileFromUrl method.

The addFileFromUrl method correctly adds a file from a URL using the _uploadCollection object and returns the output item. This method centralizes URL file addition, which enhances the code's modularity and reusability.


59-67: Refactor: Implement addFileFromUuid method.

Similar to addFileFromUrl, this method handles the addition of files using a UUID. It follows the same pattern of adding to _uploadCollection and returning the output item, maintaining consistency in the API's design.


74-88: Refactor: Implement addFileFromCdnUrl method.

This method adds a file from a CDN URL after parsing it. Error handling is present to throw an error if the URL is invalid, which is crucial for robustness. The method encapsulates CDN-specific logic, which is a good separation of concerns.


95-107: Refactor: Implement addFileFromObject method.

This method adds a file object directly. It checks if the file is an image and sets various properties accordingly. This detailed handling ensures that file properties are correctly managed and consistent across the application.


110-115: Error Handling: Correctly manage file removal by internal ID.

The removeFileByInternalId method checks if the file exists before attempting to remove it, which prevents errors from non-existent file IDs. This preemptive check enhances the robustness of the file management system.


121-136: Refactor: Implement bulk upload logic in uploadAll.

This method filters and processes multiple uploads, handling different states like 'isRemoved' and 'isUploading'. It also ensures that no action is taken if there are no items to upload, which is efficient.


139-170: Refactor: Enhance file selection dialog interaction.

The openSystemDialog method dynamically sets the file input properties based on the configuration and user options. It handles edge cases and warnings when both accept and imgOnly are set, which helps avoid configuration conflicts.

abstract/UploaderBlock.js (3)

38-47: Enhancement: Initialize upload collection and public API.

The initialization of *uploadCollection and *publicApi within UploaderBlock ensures that these components are available throughout the class. This setup enhances the modularity and reusability of the upload functionality.


59-73: Error Handling: Provide access to ValidationManager and UploaderPublicApi.

The getters for validationManager and api include error handling to ensure that these components are initialized before use. This proactive error checking prevents runtime errors and ensures the stability of the application.


Line range hint 140-311: Refactor: Implement event-driven upload logic.

This extensive block of code handles various aspects of file upload management, including updating upload states, handling file additions and removals, and emitting relevant events. The use of debounced events and detailed state management ensures that the upload process is efficient and responsive.

Copy link
Contributor

@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: 4

Outside diff range and nitpick comments (4)
types/exported.d.ts (2)

Line range hint 294-295: Remove the redundant empty export.

The empty export statement at the end of the file is redundant and can be removed to clean up the code.

- export { };

Line range hint 117-117: Specify the object shape instead of using '{}'.

Using '{}' as a type is too generic and can lead to maintenance issues. It is better to explicitly define the object shape to improve code clarity and prevent potential bugs.

- type OutputErrorTypePayload = {...};
+ type OutputErrorTypePayload = { [key: string]: any }; // Adjust according to actual expected structure
abstract/Block.js (2)

Line range hint 336-336: Clarify the use of super in a static context.

Using super in a static context can be confusing. It's clearer to use the class name instead to refer to the parent class.

- super.reg(name.startsWith(TAG_PREFIX) ? name : TAG_PREFIX + name);
+ Block.reg(name.startsWith(TAG_PREFIX) ? name : TAG_PREFIX + name);

Line range hint 339-339: Clarify the use of super in a static context.

Using super in a static context can be confusing. It's clearer to use the class name instead to refer to the parent class.

- super.reg();
+ Block.reg();
Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 6de876f and 60ba8a6.

Files selected for processing (8)
  • abstract/ActivityBlock.js (2 hunks)
  • abstract/Block.js (1 hunks)
  • abstract/CTX.js (2 hunks)
  • abstract/UploaderBlock.js (16 hunks)
  • abstract/UploaderPublicApi.js (1 hunks)
  • blocks/ExternalSource/ExternalSource.js (3 hunks)
  • types/exported.d.ts (1 hunks)
  • types/test/lr-upload-ctx-provider.test-d.tsx (4 hunks)
Files skipped from review as they are similar to previous changes (2)
  • abstract/CTX.js
  • types/test/lr-upload-ctx-provider.test-d.tsx
Additional context used
GitHub Check: build
blocks/ExternalSource/ExternalSource.js

[warning] 90-90:
'val' is defined but never used

Biome
types/exported.d.ts

[error] 294-295: This empty export is useless because there's another export or import. (lint/complexity/noUselessEmptyExport)

This import makes useless the empty export.

Safe fix: Remove this useless empty export.


[error] 117-117: Don't use '{}' as a type. (lint/complexity/noBannedTypes)

Prefer explicitly define the object shape. '{}' means "any non-nullable value".

abstract/Block.js

[error] 336-336: Using super in a static context can be confusing. (lint/complexity/noThisInStatic)

super refers to a parent class.
Unsafe fix: Use the class name instead.


[error] 339-339: Using super in a static context can be confusing. (lint/complexity/noThisInStatic)

super refers to a parent class.
Unsafe fix: Use the class name instead.

abstract/UploaderPublicApi.js

[error] 188-188: Avoid redundant double-negation. (lint/complexity/noExtraBooleanCast)

It is not necessary to use double-negation when a value will already be coerced to a boolean.
Unsafe fix: Remove redundant double-negation

Additional comments not posted (19)
abstract/ActivityBlock.js (1)

147-147: Enhancement of modal state management approved.

Setting *modalActive to false when there is no current activity ensures that the modal does not remain active erroneously, which is a good practice for maintaining UI consistency.

blocks/ExternalSource/ExternalSource.js (2)

52-52: Updated method call to use UploaderPublicApi is approved.

Using this.api.addFileFromUrl aligns with the new architecture and ensures that file handling is managed through a centralized API, which is a good design practice.


75-80: Addition of error handling for missing externalSourceType is approved.

The error handling ensures that the function does not proceed without the necessary parameter, improving the robustness of the code.

types/exported.d.ts (1)

6-6: Export of UploaderPublicApi is approved.

This export is crucial for enabling the use of UploaderPublicApi across various parts of the application, aligning with the modular architecture approach.

abstract/UploaderPublicApi.js (2)

44-107: Approval of new methods for file management.

The addition of methods such as addFileFromUrl, addFileFromUuid, addFileFromCdnUrl, and addFileFromObject enhances the API by providing structured ways to handle files from various sources. This modularity is beneficial for maintaining a clean and robust codebase.


121-136: Approval of the uploadAll method.

The uploadAll method is well-implemented, providing a robust way to handle batch file uploads by checking each file's status before initiating the upload. This method is essential for efficient batch operations.

abstract/UploaderBlock.js (13)

16-16: Code Review: Introduction of UploaderPublicApi.

The introduction of UploaderPublicApi is a key part of this PR's objective to centralize the public API functionalities. This change should streamline interactions with the uploader's functionalities and provide a cleaner API surface.


46-47: Best Practice: Initialization of UploaderPublicApi.

Initializing UploaderPublicApi conditionally is a good practice as it ensures that the instance is created only once. This helps in managing the state effectively within the class.


59-65: Error Handling: ValidationManager Accessor.

The error thrown when ValidationManager is not initialized could be more descriptive by specifying possible reasons or recovery suggestions. Enhancing this error message could aid in debugging and maintenance.
[REFACTOR_SUGGESTion]

- throw new Error('Unexpected error: ValidationManager is not initialized');
+ throw new Error('ValidationManager is not initialized. Ensure it is added to the context properly before accessing.');

111-116: Logic Review: Modal Activity Handling.

The logic to automatically set *modalActive to false if there is no current activity is sound. It helps in preventing stale modals from remaining active, which can improve user experience by avoiding confusing UI states.


148-151: Event Emission Optimization: Use of Debounce.

The use of debounce when emitting the CHANGE event is a good practice to limit the rate at which updates are processed. This can significantly enhance performance, especially in scenarios with frequent state updates.


179-180: Event Emission for File Operations.

The methods handle adding and removing files robustly by updating the state and emitting appropriate events. This is crucial for maintaining synchronization between the UI and the data model.
[APROVED]

Also applies to: 199-199


Line range hint 237-247: Event Emission on File Upload Progress and Start.

Emitting events on file upload progress and start helps in providing real-time feedback to the user, which is essential for a good user experience in file upload scenarios.


Line range hint 255-270: Handling of File Upload Success and Common Upload Success.

The handling of individual file upload successes and the overall upload success is well-implemented. Emitting different events for these scenarios allows for fine-grained control and response in the UI.


278-282: Handling of File Upload Failures.

The handling of file upload failures by emitting both specific and common failure events is a good practice. It allows for detailed error handling and user notifications.


293-293: Event Emission on File URL Change.

Emitting an event when the file URL changes is crucial for ensuring that the UI stays updated with the latest data, especially in cases where files are being manipulated or processed after upload.


319-319: Common Upload Progress Management.

The calculation and emission of common upload progress help in providing a consolidated view of the upload progress across multiple files, which is beneficial for user interfaces that need to display overall progress.


370-370: Dynamic Metadata Retrieval.

The method getMetadataFor dynamically retrieves metadata based on a configuration function, providing flexibility in how metadata is handled based on the file entry. This is a robust design that adapitates to different use cases.


404-407: Data Retrieval for Output.

The method getOutputData effectively gathers data for all entries in the uploadCollection, which is essential for operations that need to process or display all current uploads.

Comment on lines 38 to 48
if (!this.has('*uploadCollection')) {
let uploadCollection = new TypedCollection({
typedSchema: uploadEntrySchema,
watchList: ['uploadProgress', 'uploadError', 'fileInfo', 'errors', 'cdnUrl', 'isUploading'],
});
this.$['*uploadCollection'] = uploadCollection;
this.add('*uploadCollection', uploadCollection);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Potential Issue: Conditional Initialization of uploadCollection.

The conditional initialization of uploadCollection only if it does not exist might lead to scenarios where expected properties are not re-initialized on subsequent calls. Consider ensuring that the collection is always correctly initialized or reset when necessary.

Copy link
Contributor

@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: 5

Outside diff range and nitpick comments (1)
abstract/Block.js (1)

Line range hint 333-333: Clarification Needed: Use of super in static context.

The use of super in a static context can be confusing as it generally refers to the parent class's instance methods, which are not directly accessible from a static method.

- super.reg(name.startsWith(TAG_PREFIX) ? name : TAG_PREFIX + name);
+ Block.reg(name.startsWith(TAG_PREFIX) ? name : TAG_PREFIX + name);
Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 60ba8a6 and 326d1a6.

Files selected for processing (4)
  • abstract/ActivityBlock.js (5 hunks)
  • abstract/Block.js (8 hunks)
  • abstract/UploaderBlock.js (16 hunks)
  • abstract/UploaderPublicApi.js (1 hunks)
Files skipped from review as they are similar to previous changes (1)
  • abstract/ActivityBlock.js
Additional context used
Biome
abstract/Block.js

[error] 333-333: Using super in a static context can be confusing. (lint/complexity/noThisInStatic)

super refers to a parent class.
Unsafe fix: Use the class name instead.


[error] 336-336: Using super in a static context can be confusing. (lint/complexity/noThisInStatic)

super refers to a parent class.
Unsafe fix: Use the class name instead.

abstract/UploaderPublicApi.js

[error] 189-189: Avoid redundant double-negation. (lint/complexity/noExtraBooleanCast)

It is not necessary to use double-negation when a value will already be coerced to a boolean.
Unsafe fix: Remove redundant double-negation

? 'removed'
: uploadEntryData.errors.length > 0
? 'failed'
: !!uploadEntryData.fileInfo
Copy link
Contributor

Choose a reason for hiding this comment

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

Simplify Boolean Expression.

The expression !!uploadEntryData.fileInfo is redundantly cast to boolean. Since the value is already used in a Boolean context, the double negation is unnecessary.

- : !!uploadEntryData.fileInfo
+ : uploadEntryData.fileInfo
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
: !!uploadEntryData.fileInfo
: uploadEntryData.fileInfo
Tools
Biome

[error] 189-189: Avoid redundant double-negation. (lint/complexity/noExtraBooleanCast)

It is not necessary to use double-negation when a value will already be coerced to a boolean.
Unsafe fix: Remove redundant double-negation

Comment on lines +43 to +47
if (!this.has('*uploadCollection')) {
let uploadCollection = new TypedCollection({
typedSchema: uploadEntrySchema,
watchList: ['uploadProgress', 'uploadError', 'fileInfo', 'errors', 'cdnUrl', 'isUploading'],
});
this.$['*uploadCollection'] = uploadCollection;
this.add('*uploadCollection', uploadCollection);
Copy link
Contributor

Choose a reason for hiding this comment

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

Ensure Proper Initialization of uploadCollection.

The conditional initialization of uploadCollection only if it does not exist might lead to scenarios where expected properties are not re-initialized on subsequent calls. Consider ensuring that the collection is always correctly initialized or reset when necessary.

Comment on lines +164 to +165
const collectionState = this.api.getOutputCollectionState();
this.$['*collectionState'] = collectionState;
this.emit(EventType.CHANGE, () => this.getOutputCollectionState(), { debounce: true });
this.emit(EventType.CHANGE, () => this.api.getOutputCollectionState(), { debounce: true });
Copy link
Contributor

Choose a reason for hiding this comment

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

Optimize State Management Calls.

The method getOutputCollectionState is called multiple times in close succession. Consider storing its result in a local variable if the state does not change between calls to reduce overhead.

- const collectionState = this.api.getOutputCollectionState();
- this.$['*collectionState'] = collectionState;
- this.emit(EventType.CHANGE, () => this.api.getOutputCollectionState(), { debounce: true });
+ const collectionState = this.api.getOutputCollectionState();
+ this.$['*collectionList'] = collectionState;
+ this.emit(EventType.CHANGE, () => collectionState, { debounce: true });

Committable suggestion was skipped due to low confidence.

Comment on lines +75 to +80
/** @returns {UploaderPublicApi} */
get api() {
if (!this.has('*publicApi')) {
throw new Error('Unexpected error: UploaderPublicApi is not initialized');
}
return this.$['*publicApi'];
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Improve Error Handling Messages.

The error message for UploaderPublicApi initialization could be more informative by providing guidance on recovery or setup steps.

- throw new Error('Unexpected error: UploaderPublicApi is not initialized');
+ throw new Error('UploaderPublicApi is not initialized. Ensure it is added to the context properly before accessing.');
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
/** @returns {UploaderPublicApi} */
get api() {
if (!this.has('*publicApi')) {
throw new Error('Unexpected error: UploaderPublicApi is not initialized');
}
return this.$['*publicApi'];
}
/** @returns {UploaderPublicApi} */
get api() {
if (!this.has('*publicApi')) {
throw new Error('UploaderPublicApi is not initialized. Ensure it is added to the context properly before accessing.');
}
return this.$['*publicApi'];
}

Comment on lines +87 to +91
/** @returns {TypedCollection} */
get uploadCollection() {
if (!this.has('*uploadCollection')) {
throw new Error('Unexpected error: TypedCollection is not initialized');
}
return this.$['*uploadCollection'];
Copy link
Contributor

Choose a reason for hiding this comment

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

Consistency in Error Handling Messages.

This accessor for TypedCollection follows the same pattern as the previous ones. Consistency in error handling across these accessors is good, but they all suffer from the same issue of vague error messages.

- throw new Error('Unexpected error: TypedCollection is not initialized');
+ throw new Error('TypedCollection is not initialized. Ensure it is added to the context properly before accessing.');
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
/** @returns {TypedCollection} */
get uploadCollection() {
if (!this.has('*uploadCollection')) {
throw new Error('Unexpected error: TypedCollection is not initialized');
}
return this.$['*uploadCollection'];
/** @returns {TypedCollection} */
get uploadCollection() {
if (!this.has('*uploadCollection')) {
throw new Error('TypedCollection is not initialized. Ensure it is added to the context properly before accessing.');
}
return this.$['*uploadCollection'];

@uploadcare uploadcare deleted a comment from coderabbitai bot Jun 25, 2024
@uploadcare uploadcare deleted a comment from coderabbitai bot Jun 25, 2024
@nd0ut nd0ut force-pushed the feat/public-api branch from 326d1a6 to f676964 Compare June 25, 2024 13:09
Copy link
Contributor

@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: 0

Outside diff range and nitpick comments (1)
abstract/Block.js (1)

Line range hint 332-332: Clarify static method usage.

Using super in a static context can be confusing as it refers to a parent class. Consider using the class name instead to enhance clarity and maintainability.

- super.reg(name.startsWith(TAG_PREFIX) ? name : TAG_PREFIX + name);
+ Block.reg(name.startsWith(TAG_PREFIX) ? name : TAG_PREFIX + name);
Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 326d1a6 and f676964.

Files selected for processing (4)
  • abstract/ActivityBlock.js (5 hunks)
  • abstract/Block.js (8 hunks)
  • abstract/UploaderBlock.js (16 hunks)
  • abstract/UploaderPublicApi.js (1 hunks)
Files skipped from review as they are similar to previous changes (1)
  • abstract/ActivityBlock.js
Additional context used
Biome
abstract/Block.js

[error] 332-332: Using super in a static context can be confusing. (lint/complexity/noThisInStatic)

super refers to a parent class.
Unsafe fix: Use the class name instead.


[error] 335-335: Using super in a static context can be confusing. (lint/complexity/noThisInStatic)

super refers to a parent class.
Unsafe fix: Use the class name instead.

abstract/UploaderPublicApi.js

[error] 189-189: Avoid redundant double-negation. (lint/complexity/noExtraBooleanCast)

It is not necessary to use double-negation when a value will already be coerced to a boolean.
Unsafe fix: Remove redundant double-negation

Copy link
Contributor

@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

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between f676964 and aeaf459.

Files selected for processing (2)
  • abstract/UploaderBlock.js (16 hunks)
  • types/test/lr-upload-ctx-provider.test-d.tsx (4 hunks)
Additional comments not posted (10)
types/test/lr-upload-ctx-provider.test-d.tsx (4)

20-21: Refactor to use new API method call.

The change from direct method calls to using api.addFileFromUrl aligns with the refactoring to centralize API interactions through a single interface, improving modularity and maintainability.


46-46: Ensure correct type assertion for entry status.

The type assertion for state.allEntries[0].status as 'success' is specific and should accurately reflect the possible states of an entry at this point in the code. This change enhances the precision of type checking.


65-65: Expanded type assertion for entry status.

The addition of 'idle' to the possible statuses for state.allEntries[0].status is a prudent enhancement, ensuring that the type checks cover all feasible states given the context.


208-210: Enhanced type checking for activity payloads.

This change introduces a more complex type for payload.activity, which now can be either a type from ActivityBlock.activities, a string, or null. This is likely a response to the need for greater flexibility in handling different types of activities.

abstract/UploaderBlock.js (6)

14-15: Addition of crucial imports.

The imports for TypedCollection and UploaderPublicApi are essential for the new functionalities being introduced in this class, particularly with the refactoring around the public API and typed collections.


42-47: Initialization of *uploadCollection.

The conditional initialization ensures that uploadCollection is set up only if it hasn't been already. This prevents unnecessary reinitializations but might need careful handling to ensure that it doesn't lead to stale state issues in a long-lived session.
This issue was previously flagged and is still relevant.


51-52: Proper initialization of *publicApi.

This addition ensures that an instance of UploaderPublicApi is always available in the block's context, centralizing the upload functionalities and enhancing code organization.


163-165: Optimization of state management calls.

This suggestion to optimize redundant calls to getOutputCollectionState by storing its result in a local variable is still relevant and should be implemented to improve performance.
This issue was previously flagged and remains valid.


201-201: Proper event emission on file removal.

Emitting the FILE_REMOVED event with the output item ensures that any external handlers are notified about the file removal, maintaining the integrity of the UI and state.


239-239: Consistent event emission for file operations.

The changes ensure that events related to file operations (FILE_UPLOAD_PROGRESS, FILE_UPLOAD_START, FILE_UPLOAD_SUCCESS, COMMON_UPLOAD_SUCCESS, FILE_UPLOAD_FAILED, COMMON_UPLOAD_FAILED, FILE_URL_CHANGED, COMMON_UPLOAD_PROGRESS) are emitted consistently, which is crucial for maintaining a responsive and accurate UI.

Also applies to: 249-249, 257-257, 272-272, 280-284, 295-295, 321-321

Comment on lines +69 to +71
throw new Error('Unexpected error: ValidationManager is not initialized');
}
return this.$['*validationManager'];
Copy link
Contributor

Choose a reason for hiding this comment

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

Error handling for uninitialized ValidationManager.

The error message 'Unexpected error: ValidationManager is not initialized' could be improved to guide the developer more effectively.

- throw new Error('Unexpected error: ValidationManager is not initialized');
+ throw new Error('ValidationManager is not initialized. Please ensure it is correctly set up before accessing.');
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
throw new Error('Unexpected error: ValidationManager is not initialized');
}
return this.$['*validationManager'];
throw new Error('ValidationManager is not initialized. Please ensure it is correctly set up before accessing.');
}
return this.$['*validationManager'];

Comment on lines +77 to +79
throw new Error('Unexpected error: UploaderPublicApi is not initialized');
}
return this.$['*publicApi'];
Copy link
Contributor

Choose a reason for hiding this comment

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

Error handling for uninitialized UploaderPublicApi.

Similar to the previous comment, the error message here could be more informative.

- throw new Error('Unexpected error: UploaderPublicApi is not initialized');
+ throw new Error('UploaderPublicApi is not initialized. Please ensure it is correctly added to the context before use.');
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
throw new Error('Unexpected error: UploaderPublicApi is not initialized');
}
return this.$['*publicApi'];
throw new Error('UploaderPublicApi is not initialized. Please ensure it is correctly added to the context before use.');
}
return this.$['*publicApi'];

Comment on lines +89 to +91
throw new Error('Unexpected error: TypedCollection is not initialized');
}
return this.$['*uploadCollection'];
Copy link
Contributor

Choose a reason for hiding this comment

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

Error handling for uninitialized TypedCollection.

The error message needs to be more descriptive to help in debugging and setup.

- throw new Error('Unexpected error: TypedCollection is not initialized');
+ throw new Error('TypedCollection is not initialized. Check if it has been properly added to the context.');
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
throw new Error('Unexpected error: TypedCollection is not initialized');
}
return this.$['*uploadCollection'];
throw new Error('TypedCollection is not initialized. Check if it has been properly added to the context.');
}
return this.$['*uploadCollection'];

Copy link
Contributor

@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: 7

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between aeaf459 and 5f7e0f1.

Files selected for processing (4)
  • abstract/UploaderBlock.js (14 hunks)
  • abstract/UploaderPublicApi.js (1 hunks)
  • blocks/CloudImageEditor/src/svg-sprite.js (1 hunks)
  • blocks/themes/lr-basic/svg-sprite.js (1 hunks)
Files not summarized due to errors (2)
  • blocks/CloudImageEditor/src/svg-sprite.js: Error: Message exceeds token limit
  • blocks/themes/lr-basic/svg-sprite.js: Error: Message exceeds token limit
Files not reviewed due to errors (1)
  • abstract/UploaderBlock.js (no review received)
Additional context used
Biome
abstract/UploaderPublicApi.js

[error] 189-189: Avoid redundant double-negation. (lint/complexity/noExtraBooleanCast)

It is not necessary to use double-negation when a value will already be coerced to a boolean.
Unsafe fix: Remove redundant double-negation

Additional comments not posted (5)
abstract/UploaderPublicApi.js (3)

111-115: Approve error handling in removeFileByInternalId.

The method properly checks if a file exists before attempting removal, which prevents errors related to non-existent files.


118-120: Approve the implementation of removeAllFiles.

The method appropriately clears all files from the upload collection.


222-227: Approve getOutputCollectionState.

The method correctly retrieves the state of the output collection using a helper function.

blocks/themes/lr-basic/svg-sprite.js (1)

1-1: SVG Definitions Appear Correct and Well-Formed

The SVG sprite sheet is correctly formatted and defines multiple icons within a single SVG element, which is good for performance and maintainability. Each symbol has a unique ID, which is crucial for referencing these icons in the application.

blocks/CloudImageEditor/src/svg-sprite.js (1)

1-1: SVG Sprite Update Approved

The SVG sprite has been updated successfully. Ensure that the IDs and paths used in the SVG elements do not conflict with other parts of the application to avoid styling or functional issues. Also, make sure that the SVG content is sanitized to prevent any potential XSS vulnerabilities when dynamically injecting it into the DOM.

Comment on lines +122 to +136
uploadAll = () => {
const itemsToUpload = this._uploadCollection.items().filter((id) => {
const entry = this._uploadCollection.read(id);
return !entry.getValue('isRemoved') && !entry.getValue('isUploading') && !entry.getValue('fileInfo');
});

if (itemsToUpload.length === 0) {
return;
}

this._ctx.$['*uploadTrigger'] = new Set(itemsToUpload);
this._ctx.emit(
EventType.COMMON_UPLOAD_START,
/** @type {import('../types').OutputCollectionState<'uploading'>} */ (this.getOutputCollectionState()),
);
Copy link
Contributor

Choose a reason for hiding this comment

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

Optimize the uploadAll method to reduce collection reads.

The method calls read multiple times for each item, which could be optimized by reducing the number of accesses to the collection.

- const itemsToUpload = this._uploadCollection.items().filter((id) => {
-   const entry = this._uploadCollection.read(id);
-   return !entry.getValue('isRemoved') && !entry.getValue('isUploading') && !entry.getValue('fileInfo');
- });
+ const itemsToUpload = this._uploadCollection.items().filter((id) => {
+   const entry = this._uploadCollection.read(id);
+   return !(entry.isRemoved || entry.isUploading || entry.fileInfo);
+ });

Committable suggestion was skipped due to low confidence.

Comment on lines +60 to +67
addFileFromUuid = (uuid, { silent, fileName, source } = {}) => {
const internalId = this._uploadCollection.add({
uuid,
fileName: fileName ?? null,
silent: silent ?? false,
source: source ?? UploadSource.API,
});
return this.getOutputItem(internalId);
Copy link
Contributor

Choose a reason for hiding this comment

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

Refactor to ensure user input is not overridden for source.

Similar to addFileFromUrl, ensure that the source parameter respects user inputs when adding a file by UUID.

- source: source ?? UploadSource.API,
+ source: typeof source === 'undefined' ? UploadSource.API : source,
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
addFileFromUuid = (uuid, { silent, fileName, source } = {}) => {
const internalId = this._uploadCollection.add({
uuid,
fileName: fileName ?? null,
silent: silent ?? false,
source: source ?? UploadSource.API,
});
return this.getOutputItem(internalId);
addFileFromUuid = (uuid, { silent, fileName, source } = {}) => {
const internalId = this._uploadCollection.add({
uuid,
fileName: fileName ?? null,
silent: silent ?? false,
source: typeof source === 'undefined' ? UploadSource.API : source,
});
return this.getOutputItem(internalId);

Comment on lines +96 to +107
addFileFromObject = (file, { silent, fileName, source, fullPath } = {}) => {
const internalId = this._uploadCollection.add({
file,
isImage: fileIsImage(file),
mimeType: file.type,
fileName: fileName ?? file.name,
fileSize: file.size,
silent: silent ?? false,
source: source ?? UploadSource.API,
fullPath: fullPath ?? null,
});
return this.getOutputItem(internalId);
Copy link
Contributor

Choose a reason for hiding this comment

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

Refactor to respect user input for source in addFileFromObject.

Ensure that the source parameter does not inadvertently override explicit user inputs.

- source: source ?? UploadSource.API,
+ source: typeof source === 'undefined' ? UploadSource.API : source,
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
addFileFromObject = (file, { silent, fileName, source, fullPath } = {}) => {
const internalId = this._uploadCollection.add({
file,
isImage: fileIsImage(file),
mimeType: file.type,
fileName: fileName ?? file.name,
fileSize: file.size,
silent: silent ?? false,
source: source ?? UploadSource.API,
fullPath: fullPath ?? null,
});
return this.getOutputItem(internalId);
addFileFromObject = (file, { silent, fileName, source, fullPath } = {}) => {
const internalId = this._uploadCollection.add({
file,
isImage: fileIsImage(file),
mimeType: file.type,
fileName: fileName ?? file.name,
fileSize: file.size,
silent: silent ?? false,
source: typeof source === 'undefined' ? UploadSource.API : source,
fullPath: fullPath ?? null,
});
return this.getOutputItem(internalId);

Comment on lines +45 to +52
addFileFromUrl = (url, { silent, fileName, source } = {}) => {
const internalId = this._uploadCollection.add({
externalUrl: url,
fileName: fileName ?? null,
silent: silent ?? false,
source: source ?? UploadSource.API,
});
return this.getOutputItem(internalId);
Copy link
Contributor

Choose a reason for hiding this comment

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

Refactor to prevent potential overriding of user input for source.

The method addFileFromUrl uses a default value for source that might override explicit user input. Consider modifying the method to ensure user inputs are respected.

- source: source ?? UploadSource.API,
+ source: typeof source === 'undefined' ? UploadSource.API : source,
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
addFileFromUrl = (url, { silent, fileName, source } = {}) => {
const internalId = this._uploadCollection.add({
externalUrl: url,
fileName: fileName ?? null,
silent: silent ?? false,
source: source ?? UploadSource.API,
});
return this.getOutputItem(internalId);
addFileFromUrl = (url, { silent, fileName, source } = {}) => {
const internalId = this._uploadCollection.add({
externalUrl: url,
fileName: fileName ?? null,
silent: silent ?? false,
source: typeof source === 'undefined' ? UploadSource.API : source,
});
return this.getOutputItem(internalId);

Comment on lines +75 to +88
addFileFromCdnUrl = (cdnUrl, { silent, fileName, source } = {}) => {
const parsedCdnUrl = parseCdnUrl({ url: cdnUrl, cdnBase: this.cfg.cdnCname });
if (!parsedCdnUrl) {
throw new Error('Invalid CDN URL');
}
const internalId = this._uploadCollection.add({
uuid: parsedCdnUrl.uuid,
cdnUrl,
cdnUrlModifiers: parsedCdnUrl.cdnUrlModifiers,
fileName: fileName ?? parsedCdnUrl.filename ?? null,
silent: silent ?? false,
source: source ?? UploadSource.API,
});
return this.getOutputItem(internalId);
Copy link
Contributor

Choose a reason for hiding this comment

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

Ensure user input for source is respected and approve error handling.

The method correctly handles invalid CDN URLs by throwing an exception. However, ensure that the source parameter does not override user inputs.

- source: source ?? UploadSource.API,
+ source: typeof source === 'undefined' ? UploadSource.API : source,
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
addFileFromCdnUrl = (cdnUrl, { silent, fileName, source } = {}) => {
const parsedCdnUrl = parseCdnUrl({ url: cdnUrl, cdnBase: this.cfg.cdnCname });
if (!parsedCdnUrl) {
throw new Error('Invalid CDN URL');
}
const internalId = this._uploadCollection.add({
uuid: parsedCdnUrl.uuid,
cdnUrl,
cdnUrlModifiers: parsedCdnUrl.cdnUrlModifiers,
fileName: fileName ?? parsedCdnUrl.filename ?? null,
silent: silent ?? false,
source: source ?? UploadSource.API,
});
return this.getOutputItem(internalId);
addFileFromCdnUrl = (cdnUrl, { silent, fileName, source } = {}) => {
const parsedCdnUrl = parseCdnUrl({ url: cdnUrl, cdnBase: this.cfg.cdnCname });
if (!parsedCdnUrl) {
throw new Error('Invalid CDN URL');
}
const internalId = this._uploadCollection.add({
uuid: parsedCdnUrl.uuid,
cdnUrl,
cdnUrlModifiers: parsedCdnUrl.cdnUrlModifiers,
fileName: fileName ?? parsedCdnUrl.filename ?? null,
silent: silent ?? false,
source: typeof source === 'undefined' ? UploadSource.API : source,
});
return this.getOutputItem(internalId);

Comment on lines +178 to +219
getOutputItem = (entryId) => {
const uploadEntryData = /** @type {import('./uploadEntrySchema.js').UploadEntry} */ (Data.getCtx(entryId).store);

/** @type {import('@uploadcare/upload-client').UploadcareFile?} */
const fileInfo = uploadEntryData.fileInfo;

/** @type {import('../types').OutputFileEntry['status']} */
let status = uploadEntryData.isRemoved
? 'removed'
: uploadEntryData.errors.length > 0
? 'failed'
: !!uploadEntryData.fileInfo
? 'success'
: uploadEntryData.isUploading
? 'uploading'
: 'idle';

/** @type {unknown} */
const outputItem = {
uuid: fileInfo?.uuid ?? uploadEntryData.uuid ?? null,
internalId: entryId,
name: fileInfo?.originalFilename ?? uploadEntryData.fileName,
size: fileInfo?.size ?? uploadEntryData.fileSize,
isImage: fileInfo?.isImage ?? uploadEntryData.isImage,
mimeType: fileInfo?.mimeType ?? uploadEntryData.mimeType,
file: uploadEntryData.file,
externalUrl: uploadEntryData.externalUrl,
cdnUrlModifiers: uploadEntryData.cdnUrlModifiers,
cdnUrl: uploadEntryData.cdnUrl ?? fileInfo?.cdnUrl ?? null,
fullPath: uploadEntryData.fullPath,
uploadProgress: uploadEntryData.uploadProgress,
fileInfo: fileInfo ?? null,
metadata: uploadEntryData.metadata ?? fileInfo?.metadata ?? null,
isSuccess: status === 'success',
isUploading: status === 'uploading',
isFailed: status === 'failed',
isRemoved: status === 'removed',
errors: /** @type {import('../types/exported.js').OutputFileEntry['errors']} */ (uploadEntryData.errors),
status,
};

return /** @type {import('../types/exported.js').OutputFileEntry<TStatus>} */ (outputItem);
Copy link
Contributor

Choose a reason for hiding this comment

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

Fix the redundant double-negation and approve getOutputItem.

The method correctly retrieves file information and determines its status. Address the previously flagged double-negation issue.

- : !!uploadEntryData.fileInfo
+ : uploadEntryData.fileInfo
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
getOutputItem = (entryId) => {
const uploadEntryData = /** @type {import('./uploadEntrySchema.js').UploadEntry} */ (Data.getCtx(entryId).store);
/** @type {import('@uploadcare/upload-client').UploadcareFile?} */
const fileInfo = uploadEntryData.fileInfo;
/** @type {import('../types').OutputFileEntry['status']} */
let status = uploadEntryData.isRemoved
? 'removed'
: uploadEntryData.errors.length > 0
? 'failed'
: !!uploadEntryData.fileInfo
? 'success'
: uploadEntryData.isUploading
? 'uploading'
: 'idle';
/** @type {unknown} */
const outputItem = {
uuid: fileInfo?.uuid ?? uploadEntryData.uuid ?? null,
internalId: entryId,
name: fileInfo?.originalFilename ?? uploadEntryData.fileName,
size: fileInfo?.size ?? uploadEntryData.fileSize,
isImage: fileInfo?.isImage ?? uploadEntryData.isImage,
mimeType: fileInfo?.mimeType ?? uploadEntryData.mimeType,
file: uploadEntryData.file,
externalUrl: uploadEntryData.externalUrl,
cdnUrlModifiers: uploadEntryData.cdnUrlModifiers,
cdnUrl: uploadEntryData.cdnUrl ?? fileInfo?.cdnUrl ?? null,
fullPath: uploadEntryData.fullPath,
uploadProgress: uploadEntryData.uploadProgress,
fileInfo: fileInfo ?? null,
metadata: uploadEntryData.metadata ?? fileInfo?.metadata ?? null,
isSuccess: status === 'success',
isUploading: status === 'uploading',
isFailed: status === 'failed',
isRemoved: status === 'removed',
errors: /** @type {import('../types/exported.js').OutputFileEntry['errors']} */ (uploadEntryData.errors),
status,
};
return /** @type {import('../types/exported.js').OutputFileEntry<TStatus>} */ (outputItem);
getOutputItem = (entryId) => {
const uploadEntryData = /** @type {import('./uploadEntrySchema.js').UploadEntry} */ (Data.getCtx(entryId).store);
/** @type {import('@uploadcare/upload-client').UploadcareFile?} */
const fileInfo = uploadEntryData.fileInfo;
/** @type {import('../types').OutputFileEntry['status']} */
let status = uploadEntryData.isRemoved
? 'removed'
: uploadEntryData.errors.length > 0
? 'failed'
: uploadEntryData.fileInfo
? 'success'
: uploadEntryData.isUploading
? 'uploading'
: 'idle';
/** @type {unknown} */
const outputItem = {
uuid: fileInfo?.uuid ?? uploadEntryData.uuid ?? null,
internalId: entryId,
name: fileInfo?.originalFilename ?? uploadEntryData.fileName,
size: fileInfo?.size ?? uploadEntryData.fileSize,
isImage: fileInfo?.isImage ?? uploadEntryData.isImage,
mimeType: fileInfo?.mimeType ?? uploadEntryData.mimeType,
file: uploadEntryData.file,
externalUrl: uploadEntryData.externalUrl,
cdnUrlModifiers: uploadEntryData.cdnUrlModifiers,
cdnUrl: uploadEntryData.cdnUrl ?? fileInfo?.cdnUrl ?? null,
fullPath: uploadEntryData.fullPath,
uploadProgress: uploadEntryData.uploadProgress,
fileInfo: fileInfo ?? null,
metadata: uploadEntryData.metadata ?? fileInfo?.metadata ?? null,
isSuccess: status === 'success',
isUploading: status === 'uploading',
isFailed: status === 'failed',
isRemoved: status === 'removed',
errors: /** @type {import('../types/exported.js').OutputFileEntry['errors']} */ (uploadEntryData.errors),
status,
};
return /** @type {import('../types/exported.js').OutputFileEntry<TStatus>} */ (outputItem);
Tools
Biome

[error] 189-189: Avoid redundant double-negation. (lint/complexity/noExtraBooleanCast)

It is not necessary to use double-negation when a value will already be coerced to a boolean.
Unsafe fix: Remove redundant double-negation

Comment on lines +139 to +170
/** @param {{ captureCamera?: boolean }} options */
openSystemDialog = (options = {}) => {
let accept = serializeCsv(mergeFileTypes([this.cfg.accept ?? '', ...(this.cfg.imgOnly ? IMAGE_ACCEPT_LIST : [])]));

if (this.cfg.accept && !!this.cfg.imgOnly) {
console.warn(
'There could be a mistake.\n' +
'Both `accept` and `imgOnly` parameters are set.\n' +
'The value of `accept` will be concatenated with the internal image mime types list.',
);
}
const fileInput = document.createElement('input');
fileInput.type = 'file';
fileInput.multiple = this.cfg.multiple;
if (options.captureCamera) {
fileInput.capture = this.cfg.cameraCapture;
fileInput.accept = 'image/*';
} else {
fileInput.accept = accept;
}
fileInput.dispatchEvent(new MouseEvent('click'));
fileInput.onchange = () => {
// @ts-ignore TODO: fix this
[...fileInput['files']].forEach((file) =>
this.addFileFromObject(file, { source: options.captureCamera ? UploadSource.CAMERA : UploadSource.LOCAL }),
);
// To call uploadTrigger UploadList should draw file items first:
this._ctx.$['*currentActivity'] = ActivityBlock.activities.UPLOAD_LIST;
this._ctx.setOrAddState('*modalActive', true);
// @ts-ignore TODO: fix this
fileInput['value'] = '';
};
Copy link
Contributor

Choose a reason for hiding this comment

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

Address TypeScript issue and approve openSystemDialog.

The method effectively handles different file input configurations. However, address the TypeScript issue noted in the TODO comment.

- // @ts-ignore TODO: fix this
+ // Properly type the 'files' property

Committable suggestion was skipped due to low confidence.

Copy link
Contributor

@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: 0

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 5f7e0f1 and 665e263.

Files selected for processing (1)
  • abstract/UploaderBlock.js (14 hunks)
Additional comments not posted (12)
abstract/UploaderBlock.js (12)

42-47: Ensure Proper Initialization of uploadCollection.

The conditional initialization of uploadCollection only if it does not exist might lead to scenarios where expected properties are not re-initialized on subsequent calls. Consider ensuring that the collection is always correctly initialized or reset when necessary.


50-52: Initialization of UploaderPublicApi.

The addition of UploaderPublicApi is a direct implementation of the PR's objective to extract the public API. This should enhance modularity and maintainability. Ensure that all dependencies and interactions with this new API are thoroughly tested.


69-71: Error handling for uninitialized ValidationManager.

The error message 'Unexpected error: ValidationManager is not initialized' could be improved to guide the developer more effectively.


77-79: Error handling for uninitialized UploaderPublicApi.

Similar to the previous comment, the error message here could be more informative.


89-91: Error handling for uninitialized TypedCollection.

The error message needs to be more descriptive to help in debugging and setup.


127-129: Optimized state management for modal activity.

Adjusting modalActive to false when no current activity exists is a clean and effective way to manage the UI state. This change should help prevent any UI inconsistencies due to stale modal states.


163-165: Optimize State Management Calls.

The method getOutputCollectionState is called multiple times in close succession. Consider storing its result in a local variable if the state does not change between calls to reduce overhead.


186-186: Event Emission for File Operations.

Emitting events when files are added or removed is crucial for maintaining sync with the UI and other components. Ensure that these events are handled appropriately in the UI to reflect the changes.

Also applies to: 201-201


239-239: Enhanced feedback for file upload operations.

Emitting specific events for different stages of the file upload process (progress, start, success, and failure) is a good practice. It provides clear feedback to the user and helps in debugging and monitoring the state of uploads.

Also applies to: 249-249, 257-257, 268-272


289-291: Common Upload Success Event.

Emitting a common success event when all files are successfully uploaded is a good user experience practice. It simplifies handling upload success in client applications.


325-325: Consistent Upload Progress Reporting.

Using the getOutputCollectionState to report upload progress ensures consistency in how upload progress is calculated and reported. This is crucial for maintaining a reliable user experience.


376-376: Dynamic Metadata Retrieval.

The method getMetadataFor dynamically retrieves metadata based on the configuration. This flexibility is beneficial for adapting to different metadata requirements without changing the underlying implementation.

Copy link
Contributor

@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: 0

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 665e263 and ad563aa.

Files selected for processing (1)
  • blocks/FileItem/file-item.css (1 hunks)
Additional comments not posted (1)
blocks/FileItem/file-item.css (1)

11-18: Well-documented workaround for Chrome rendering issue.

The addition of min-height: 1px; is a straightforward and minimal workaround to address a specific rendering issue in Chrome-based browsers. The detailed comment explaining this workaround is clear and helps maintain the readability and maintainability of the code. This ensures that future developers can understand the reason behind this specific style rule.

@nd0ut nd0ut force-pushed the feat/public-api branch from ad563aa to 463a852 Compare June 27, 2024 13:14
Copy link
Contributor

@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: 0

Outside diff range and nitpick comments (1)
abstract/Block.js (1)

Line range hint 332-332: Misuse of super in static context.

The static analysis tool has correctly identified the use of super in a static context, which can lead to confusion and potential errors.

- super.reg();
+ Block.reg();
- super.reg(name.startsWith(TAG_PREFIX) ? name : TAG_PREFIX + name);
+ Block.reg(name.startsWith(TAG_PREFIX) ? name : TAG_PREFIX + name);

Also applies to: 335-335

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between ad563aa and 463a852.

Files selected for processing (5)
  • abstract/Block.js (9 hunks)
  • blocks/CloudImageEditor/src/svg-sprite.js (1 hunks)
  • blocks/FileItem/file-item.css (1 hunks)
  • blocks/themes/lr-basic/svg-sprite.js (1 hunks)
  • build-svg-sprite.js (1 hunks)
Files not summarized due to errors (1)
  • blocks/themes/lr-basic/svg-sprite.js: Error: Message exceeds token limit
Files skipped from review as they are similar to previous changes (1)
  • blocks/FileItem/file-item.css
Additional context used
Biome
abstract/Block.js

[error] 332-332: Using super in a static context can be confusing.

super refers to a parent class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)


[error] 335-335: Using super in a static context can be confusing.

super refers to a parent class.
Unsafe fix: Use the class name instead.

(lint/complexity/noThisInStatic)

Additional comments not posted (7)
build-svg-sprite.js (1)

72-74: Refinement in template string handling.

The changes made to the template string ensure proper formatting by trimming unnecessary spaces and adding a newline at the end. This is a good practice for maintaining clean and predictable output files.

abstract/Block.js (4)

26-27: Addition of a protected property.

The requireCtxName property has been added and marked as protected, which is appropriate for properties that should be modifiable only within the class or its subclasses.


57-57: Addition of a private method for pluralization.

The pluralize method is a good addition for handling localization concerns directly within the class. This encapsulation of functionality improves maintainability.


71-71: Enhanced localization binding.

The bindL10n method has been added to strengthen the localization capabilities of the class, allowing dynamic updates based on locale changes.


125-125: Lifecycle and utility methods enhancements.

The additions to the lifecycle methods (connectedCallback, disconnectedCallback, initCallback) and utility methods (localeManager, a11y, destroyCallback) are well placed and enhance the functionality and robustness of the class.

Also applies to: 157-157, 163-163, 189-189, 198-198, 210-210

blocks/CloudImageEditor/src/svg-sprite.js (1)

1-1: Updated SVG definitions.

The updated SVG symbols for various icons ensure that the visual components of the CloudImageEditor are modern and visually consistent. This update is crucial for maintaining a good user interface.

blocks/themes/lr-basic/svg-sprite.js (1)

1-1: SVG Content Review: Check for Correctness and Consistency

The SVG content appears to be well-formed with all symbols correctly defined. Ensure that the updated symbols (as mentioned in the summary) are tested across different browsers to verify their appearance and behavior.

Copy link
Contributor

@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: 0

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 463a852 and a9b1825.

Files selected for processing (1)
  • blocks/FileItem/file-item.css (2 hunks)
Files skipped from review as they are similar to previous changes (1)
  • blocks/FileItem/file-item.css

@egordidenko egordidenko merged commit ea29dd2 into main Jul 2, 2024
1 check passed
@egordidenko egordidenko deleted the feat/public-api branch July 2, 2024 12:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

2 participants