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

#1685 Custom options for @pixiebrix/data/get and @pixiebrix/data/put bricks #1750

Merged
merged 19 commits into from Oct 28, 2021

Conversation

BALEHOK
Copy link
Contributor

@BALEHOK BALEHOK commented Oct 25, 2021

Resolves #1685

DB Selector

image

Create DB modal

image

image

import React from "react";
import { Button } from "react-bootstrap";

type MenuListWithAddButtonProps = {
Copy link
Contributor

Choose a reason for hiding this comment

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

If we're not exporting the component and there's just one component in the file, I think it's OK to use "OwnProps" or another short type name

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In many cases the props type is called {ComponentName}Props. It always makes a naming pair of component-props and does not depend on exported members.

I'm for consistency. Why not to settle on the convention now. Options:

  1. Do not define a type at all unless you need to export... or the type definition is huge (10+ line) example.
  2. Always define the props type. Call it OwnProps if not exported, call it {ComponentName}Props if/when you export the type.
  3. Always define the props type and call it {ComponentName}Props.

@twschiller
cc @BLoe

Copy link
Collaborator

Choose a reason for hiding this comment

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

My thoughts are that if the type is not exported, I don't much care what you name it, I care much, much more about how the type is structured, so I can read it and understand what's going on with a component.

If it's exported it should be {ComponentName}Props, that's about the only strict rule I'd feel strongly about here.

});

if ("error" in result) {
console.error(result.error);
Copy link
Contributor

@twschiller twschiller Oct 26, 2021

Choose a reason for hiding this comment

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

  • Fix error handling


const [addDatabaseToGroup] = useAddDatabaseToGroupMutation();

const onSave = async ({ name, organizationId, groupId }: DatabaseConfig) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

See useUserAction

Copy link
Contributor Author

@BALEHOK BALEHOK Oct 26, 2021

Choose a reason for hiding this comment

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

  1. appBaseQuery doesn't throw, it returns a result with an error -> useUserAction will not handle the error properly.
  2. useUserAction tries to get the error message from AxiosError, but appBaseQuery kinda obfurscates the error -> useUserAction logic doesn't help.
  3. onSave conditionally makes 2 requests and handles the result of each. There's no need to update the UI state either.

Not sure howuseUserAction can help here?

src/types/contract.ts Outdated Show resolved Hide resolved
src/services/api.ts Outdated Show resolved Hide resolved
}),
getOrganizations: builder.query<Organization[], void>({
query: () => ({ url: "/api/organizations/", method: "get" }),
providesTags: ["Organizations"],
transformResponse: (
baseQueryReturnValue: Array<components["schemas"]["Organization"]>
Copy link
Contributor

Choose a reason for hiding this comment

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

We've been referring to the type exported from the the contract.ts file instead of using components["schema"] in code

Also, make any manual updates to the schema in contracts.ts instead of using any below. See the examples in contract.ts that use "&" to refine the types from swagger.ts

Copy link
Contributor Author

@BALEHOK BALEHOK Oct 26, 2021

Choose a reason for hiding this comment

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

make any manual updates to the schema in contracts.ts

This is my intention.
API returns Organization without isAdmin (or role) property. src/types/contract.ts add it at line 40. But this is only on the types level.
Here transformResponse reserves the object from API (which is actually of type Array<components["schemas"]["Organization"]>) and converts it to what we want in the Extension project - Organization defined in contracts.ts.

): Organization[] =>
baseQueryReturnValue.map((apiOrganization) => ({
...apiOrganization,
/*
Copy link
Contributor

Choose a reason for hiding this comment

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

Use //-style comments. Your IDE should have a shortcut for commenting multiple lines

meta: { organizationId },
includeRequestData: true,
}),
providesTags: ["Groups"],
Copy link
Contributor

Choose a reason for hiding this comment

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

Don't these tags need to include the id of the organization? https://redux-toolkit.js.org/rtk-query/api/createApi#providestags. Or does the meta automatically handle that?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Meta is a means of getting request parameter in the transformResponse function.
I think you're right, the organization id should be included in tags.

const onSave = async ({ name, organizationId, groupId }: DatabaseConfig) => {
const result = await createDatabase({
name,
organizationId,
Copy link
Contributor

Choose a reason for hiding this comment

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

Is organizationId "" at this point? Or is it null? See comment on the type definition

Copy link
Contributor Author

Choose a reason for hiding this comment

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

organizationId can be an ID or empty (null, undefined, blank).

onClose();
};

let organizationOptions = (organizations || [])
Copy link
Contributor

Choose a reason for hiding this comment

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

Extract into helper method, e.g., selectOrganizationOptions(organizations)

Use the null coalescing operator ??, not ||

(o) => o.id === db.organization_id
);
const dbName = organization
? `${db.name} [${organization.name}]`
Copy link
Contributor

Choose a reason for hiding this comment

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

See http://github.com/pixiebrix/pixiebrix-extension/blob/feature/1685-data-get-put/src/hooks/auth.ts#L114-L114 for our current convention for showing organization name in options drop downs (it uses an mdash)

@BALEHOK BALEHOK marked this pull request as ready for review October 27, 2021 08:18
@@ -78,6 +80,9 @@ const SelectWidget = <TOption extends Option<TOption["value"]>>({
>);
};

const selectValue =
options?.find((option: TOption) => value === option.value) || null;
Copy link
Contributor

Choose a reason for hiding this comment

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

Use the null coalescing operator ??, not ||

Copy link
Contributor

@twschiller twschiller left a comment

Choose a reason for hiding this comment

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

@BALEHOK this is ready to merge once you make one small improvement

  • When you add a database with create database, it should be selected from the dropdown

Also, some general comments:

@twschiller twschiller added this to the 1.4.5 milestone Oct 27, 2021
Comment on lines 47 to 52
organizationId: string | null;

/**
* Id of a Group for shared DB.
* Blank for a Personal DB
* UUID of a Group for a shared DB, or null/empty for a personal DB.
*/
groupId: string;
groupId: string | null;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@twschiller This refers to the rule strictNullChecks. It is disabled so any property can be null or undefined. Seems that <type> | null is not really consistent with the code style, it isn't widely adopted on the project.

Copy link
Contributor

Choose a reason for hiding this comment

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

This refers to the rule strictNullChecks

I'm not sure I'm following? Even though strictNullChecks is not enabled, we've always been marking which fields are optional with the (?) or accept null. Otherwise the type is inconsistent with the documentation above it

@twschiller twschiller merged commit 732f978 into main Oct 28, 2021
@twschiller twschiller deleted the feature/1685-data-get-put branch October 28, 2021 12:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Custom options for @pixiebrix/data/get and @pixiebrix/data/put bricks
3 participants