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

[ENH] Implemented upload data dictionary component #50

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Open

Conversation

rmanaem
Copy link
Contributor

@rmanaem rmanaem commented Feb 20, 2025

Checklist

This section is for the PR reviewer

  • PR has an interpretable title with a prefix ([ENH], [FIX], [REF], [TST], [CI], [MNT], [INF], [MODEL], [DOC]) (see our Contributing Guidelines for more info)
  • PR has a label for the release changelog or skip-release (to be applied by maintainers only)
  • PR links to GitHub issue with mention Closes #XXXX
  • Tests pass
  • Checks pass

For new features:

  • Tests have been added

For bug fixes:

  • There is at least one test that would fail under the original bug conditions.

Summary by Sourcery

Implements a data dictionary upload feature, allowing users to upload a JSON file to provide metadata descriptions for data table columns. The file uploader component is enhanced with disabled state and tooltip support. This pull request closes issues #39 and #41.

New Features:

  • Introduces a data dictionary upload component to allow users to upload a JSON file containing metadata descriptions for the columns in the data table.
  • Adds a tooltip to the file uploader to indicate when uploading is disabled and why.

Enhancements:

  • Updates the file uploader component to support disabling the upload functionality and displaying a tooltip when disabled.
  • Improves the visual appearance of the file uploader component, including changes to colors and cursor styles.

Build:

  • Adds ramda and @microlink/react-json-view as project dependencies.

Chores:

  • Adds mock data for data dictionary and updated columns for testing purposes.

Copy link

sourcery-ai bot commented Feb 20, 2025

Reviewer's Guide by Sourcery

This pull request introduces the ability to upload a data dictionary file to enhance column descriptions, and enhances the FileUploader component with a disabled state and tooltip. The data dictionary upload functionality allows users to provide a JSON file that maps column headers to descriptions, which are then used to update the column metadata in the application. The FileUploader component was updated to allow disabling the upload functionality and providing a tooltip explaining why it is disabled.

Sequence diagram for uploading a data dictionary file

sequenceDiagram
  participant User
  participant UploadCard
  participant FileUploader
  participant DataStore

  User->>UploadCard: Clicks to upload data dictionary
  UploadCard->>FileUploader: handleClickToUpload()
  FileUploader->>User: Selects a .json file
  User->>FileUploader: Chooses file
  FileUploader->>FileUploader: handleFileUpload(event)
  FileUploader->>UploadCard: onFileUpload(file)
  UploadCard->>DataStore: processDataDictionaryFile(file)
  DataStore->>DataStore: Reads file content
  DataStore->>DataStore: Parses JSON to DataDictionary
  DataStore->>DataStore: Updates columns with descriptions
  DataStore->>DataStore: setUploadedDataDictionaryFileName(fileName)
  DataStore->>DataStore: setDataDictionary(dataDictionary)
  DataStore-->>UploadCard: Resolves promise
  UploadCard-->>User: Updates UI with preview
Loading

Updated class diagram for FileUploader component

classDiagram
  class FileUploader {
    +displayText: string
    +handleClickToUpload: () => void
    +handleDrop: (event: React.DragEvent<HTMLDivElement>) => void
    +handleDragOver: (event: React.DragEvent<HTMLDivElement>) => void
    +handleFileUpload: (event: React.ChangeEvent<HTMLInputElement>) => void
    +fileInputRef: React.RefObject<HTMLInputElement>
    +allowedFileType: string
    +disabled?: boolean
    +tooltipContent?: string
  }
  note for FileUploader "Added 'disabled' and 'tooltipContent' properties"
Loading

Updated class diagram for DataStore

classDiagram
  class DataStore {
    +dataTable: DataTable
    +columns: Columns
    +uploadedDataDictionary: DataDictionary
    +uploadedDataTableFileName: string | null
    +uploadedDataDictionaryFileName: string | null
    +setDataTable: (data: DataTable) => void
    +initializeColumns: (data: Columns) => void
    +setDataDictionary: (data: DataDictionary) => void
    +setUploadedDataTableFileName: (fileName: string | null) => void
    +setUploadedDataDictionaryFileName: (fileName: string | null) => void
    +processDataTableFile: (file: File) => Promise<void>
    +processDataDictionaryFile: (file: File) => Promise<void>
  }
  note for DataStore "Added data dictionary related properties and methods"
Loading

File-Level Changes

Change Details Files
Added a disabled prop and tooltipContent prop to the FileUploader component to control its interactive state and provide contextual help.
  • Added disabled and tooltipContent props to the FileUploader component's props interface.
  • Modified the component's logic to disable click, drag, and drop functionalities when disabled is true.
  • Added a Tooltip component to display tooltipContent when the FileUploader is disabled.
  • Updated the styling to reflect the disabled state, including cursor, border, and background color changes.
  • Added default values for the disabled and tooltipContent props.
src/components/FileUploader.tsx
Implemented data dictionary upload and processing functionality.
  • Added uploadedDataDictionary and uploadedDataDictionaryFileName to the data store.
  • Added setDataDictionary and setUploadedDataDictionaryFileName actions to the data store.
  • Implemented processDataDictionaryFile to read and parse the data dictionary file, then update the column descriptions in the data store.
  • Added a new UploadCard component for uploading the data dictionary.
  • Added a new DataDictionaryPreview component to display the uploaded data dictionary.
  • Added logic to disable the data dictionary file uploader if a data table hasn't been uploaded yet.
  • Added mock data for data dictionary and updated columns.
  • Added DataDictionary type definition.
src/stores/data.ts
src/utils/mocks.ts
src/utils/types.ts
src/components/Upload.tsx
src/components/UploadCard.tsx
src/components/DataDictionaryPreview.tsx
Added component tests for the FileUploader and UploadCard components.
  • Added a test case to verify the disabled state of the FileUploader component.
  • Added a test case to verify the rendering of the FileUploaderDisplayText prop in the UploadCard component.
cypress/component/UploadCard.cy.tsx
cypress/component/FileUploader.cy.tsx

Assessment against linked issues

Issue Objective Addressed Explanation
#39 Implement the ability to upload a .json file.
#39 Implement a preview of the uploaded file, with a collapsable option.
#39 Implement a test for the new component.
#41 Update the state with the content of the re-uploaded data dictionary file, specifically updating the 'column' object in the state.
#41 Implement unit tests for the state actions related to data dictionary re-uploading. The PR does not include any unit tests.

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. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the 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 exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!
  • Generate a plan of action for an issue: Comment @sourcery-ai plan on
    an issue to generate a plan of action for it.

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

Copy link

netlify bot commented Feb 20, 2025

Deploy Preview for staging-annotation ready!

Name Link
🔨 Latest commit 4eda49a
🔍 Latest deploy log https://app.netlify.com/sites/staging-annotation/deploys/67b7a28071e964000878e40d
😎 Deploy Preview https://deploy-preview-50--staging-annotation.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

Copy link

codecov bot commented Feb 20, 2025

Codecov Report

Attention: Patch coverage is 80.72289% with 16 lines in your changes missing coverage. Please review.

Project coverage is 81.09%. Comparing base (34f7aee) to head (4eda49a).

Files with missing lines Patch % Lines
src/components/CustomDataDictionaryPreview.tsx 73.07% 7 Missing ⚠️
src/stores/data.ts 79.16% 5 Missing ⚠️
src/components/Upload.tsx 76.92% 3 Missing ⚠️
src/components/DataDictionaryPreview.tsx 66.66% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main      #50      +/-   ##
==========================================
+ Coverage   80.48%   81.09%   +0.60%     
==========================================
  Files          17       19       +2     
  Lines         123      201      +78     
  Branches       17       38      +21     
==========================================
+ Hits           99      163      +64     
- Misses         24       38      +14     
Flag Coverage Δ
tests 81.09% <80.72%> (+0.60%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@rmanaem rmanaem requested a review from surchs February 21, 2025 17:03
@rmanaem rmanaem added the pr-minor Non-breaking feature or enhancement, will increment minor version (0.+1.0) label Feb 21, 2025
Copy link

@surchs surchs left a comment

Choose a reason for hiding this comment

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

Hey @rmanaem, thanks a lot for the PR! The UI looks really very nice, and the functionality is great. My comments are mainly about the structure of the components and readability. I think now is the best time to set the theme for keeping things clean and easy to understand, it'll only get more complex from here.

So I left comments in a couple of places where I currently find it tricky to follow the component. the main issue is, as they say, debugging is twice as hard as writing code - so if we barely get it while we write it / it's fresh, then we won't get it when it breaks....

Take a look

@@ -40,5 +40,6 @@ module.exports = {
*/
'@stylistic/indent': 'off',
'@stylistic/comma-dangle': 'off',
'@typescript-eslint/no-unused-vars': 'off',
Copy link

Choose a reason for hiding this comment

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

Why is this needed now? Or: please put comment above on why we disable it. Because that seems like a useful linting rule to me

Comment on lines +53 to +54
data-cy={`${key}-expand-collapse-button`}
>
Copy link

Choose a reason for hiding this comment

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

I know this component isn't used yet, but the cypress selector here is not specific enough. Maybe leave a TODO comment here to revisit the selector specificity when this component is to be used

return (
<div>
<IconButton
onClick={() => toggleExpand(key)}
Copy link

Choose a reason for hiding this comment

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

key is not going to be unique, e.g. many columns will have "Annotations". I won't look much closer since this component isn't use. But I suggest you at least add a big TODO comment above this section to remind us to fix this if we decide to move this component live

Comment on lines +15 to 25
displayText: string;
handleClickToUpload: () => void;
handleDrop: (event: React.DragEvent<HTMLDivElement>) => void;
handleDragOver: (event: React.DragEvent<HTMLDivElement>) => void;
handleFileUpload: (event: React.ChangeEvent<HTMLInputElement>) => void;
fileInputRef: React.RefObject<HTMLInputElement>;
allowedFileType: string;
disabled?: boolean;
tooltipContent?: string;
}) {
const theme = useTheme();
Copy link

Choose a reason for hiding this comment

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

I liked the interface use before. Why did you go back to defining the types inline here?

@@ -27,4 +27,20 @@ describe('FileUploader', () => {
cy.get('[data-cy="upload-area"]').should('be.visible');
cy.get('[data-cy="upload-area"]').should('contain', 'Upload your file (.csv)');
});
it('Should disable the upload area', () => {
Copy link

Choose a reason for hiding this comment

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

Suggested change
it('Should disable the upload area', () => {
it('Upload area is inactive when component is disabled', () => {

Comment on lines +40 to +45
className={`mx-auto max-w-[768px] rounded-3xl border-2 border-dashed p-8 transition-colors ${
disabled
? 'cursor-not-allowed border-gray-200 bg-gray-100'
: 'hover:border-primary-main cursor-pointer border-gray-300'
}`}
onClick={handleClick}
Copy link

Choose a reason for hiding this comment

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

There is quite a bit of inline CSS going on here. That makes the component hard to read. And probably also makes it tougher to change the styling later on. I think we should try to factor these things out of the render portion of the app and define such styles separately before the component, similar to how we define interfaces for the types. I think https://mui.com/system/styled/ should do the trick for that - e.g. like so https://mui.com/system/styled/#basic-usage

Comment on lines 21 to 26
dataTable: {},
columns: {},
uploadedDataDictionary: {},
uploadedDataTableFileName: null,
uploadedDataDictionaryFileName: null,
setDataTable: (data: DataTable) => set({ dataTable: data }),
Copy link

Choose a reason for hiding this comment

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

I find this store / section hard to read and think through. Couple ideas:

Is it really necessary to have dataTable, columns, uploadedDataTableFileName to all be separate store variables? I understand the benefit of avoiding deep updates, but all of these things are very closely releated, so representing them in a single object would make sense, no? If this is a big change, please make an issue to discuss instead.

We can make better use of whitespace and comments here to structure the sections and make them easier to understand. E.g. first section: // Data Table, followed by the variables, empty line, then all the setter and getter methods for dataTable stuff. Second section // Data dictionary, followed by same for dataDictionary.

This early in the process, it really pays of to think about cleanliness and structure. Once we start adding more things it'll get harder and harder to keep things clean and easy to understand

Comment on lines +107 to +111
UploadCard.defaultProps = {
diableFileUploader: false,
FileUploaderToolTipContent: 'Uploading is disabled',
};

Copy link

Choose a reason for hiding this comment

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

Is there a reason you use this format? If not, let's go with https://react.dev/learn/passing-props-to-a-component#specifying-a-default-value-for-a-prop. This seems to be the recommended approach for functional components and I think it also helps a lot with readability.

If there is a reason to keep using this format, please add a comment above the section to explain why, and then I'd say move the defaultProps section above the component declaration - because we'll most likely read this file top to bottom.

Comment on lines +88 to +92
FileUploader.defaultProps = {
disabled: false,
tooltipContent: 'Uploading is disabled',
};

Copy link

Choose a reason for hiding this comment

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

Same comment here as in UploadCard about the defaults. https://react.dev/learn/passing-props-to-a-component#specifying-a-default-value-for-a-prop or please comment why not like that and move above component for readability

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
pr-minor Non-breaking feature or enhancement, will increment minor version (0.+1.0)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Re-uploading data dictionary and updating the store Upload data dictionary component ui
2 participants