Skip to content

feat(site): add stop and start batch actions #10565

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

Merged
merged 9 commits into from
Nov 8, 2023

Conversation

BrunoQuaresma
Copy link
Collaborator

Demo:

Screen.Recording.2023-11-07.at.15.13.17.mov

@BrunoQuaresma BrunoQuaresma requested a review from a team November 7, 2023 19:35
@BrunoQuaresma BrunoQuaresma self-assigned this Nov 7, 2023
@BrunoQuaresma BrunoQuaresma requested review from Parkreiner and removed request for a team November 7, 2023 19:35
@BrunoQuaresma BrunoQuaresma changed the title Bq/start stop bulk actions feat(site): add stop and stop batch actions Nov 7, 2023
Copy link
Member

@Parkreiner Parkreiner left a comment

Choose a reason for hiding this comment

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

Looks really good!
Just had some questions/comments. One of them deals with type-safety, but I don't think it's big enough to block you over

<MoreVertOutlined />
</IconButton>
);
return cloneElement(children as ReactElement, {
Copy link
Member

Choose a reason for hiding this comment

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

Is this type-safe? My worry is that it looks like there's nothing restricting the type of children at the type level, so if someone accidentally passes in a string or a primitive as a prop, they would get a more cryptic runtime error

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I swear I tried my best to get a correct type for this without success :(

@@ -92,12 +87,18 @@ const WorkspacesPage: FC = () => {
}, [experimentEnabled, data, filterProps.filter.query]);
const updateWorkspace = useWorkspaceUpdate(queryKey);
const [checkedWorkspaces, setCheckedWorkspaces] = useState<Workspace[]>([]);
const [isDeletingAll, setIsDeletingAll] = useState(false);
const [isConfirmingDeleteAll, setIsConfirmingDeleteAll] = useState(false);
Copy link
Member

Choose a reason for hiding this comment

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

Really like the name change

const [urlSearchParams] = searchParamsResult;
const { entitlements } = useDashboard();
const canCheckWorkspaces =
entitlements.features["workspace_batch_actions"].enabled;
const permissions = usePermissions();
const batchActions = useBatchActions({
onSuccess: async () => {
await refetch();
Copy link
Member

Choose a reason for hiding this comment

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

Does this need to be awaited? I'm wondering if we could just refetch without await, so the state can be cleared out faster

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, it is needed because we only want to remove the loading state from this action when the new info is on the screen.

@@ -92,12 +87,18 @@ const WorkspacesPage: FC = () => {
}, [experimentEnabled, data, filterProps.filter.query]);
const updateWorkspace = useWorkspaceUpdate(queryKey);
const [checkedWorkspaces, setCheckedWorkspaces] = useState<Workspace[]>([]);
Copy link
Member

@Parkreiner Parkreiner Nov 7, 2023

Choose a reason for hiding this comment

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

Something I've been wondering about for a little bit: does it make sense to copy the checked workspaces into a separate piece of state, or could this be replaced with a Set object containing the IDs of workspaces that have been checked? That way, the original array and the Set could be cross-referenced

I know the current implementation simplifies the setup for calling the batch action functions, but I guess I've just been worried that with state values that lean more redundant, there might be bugs where they get out of sync down the line

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I think so, I just don't see this being used very often. Would you have any extra resources sharing the benefits of this approach?

Copy link
Member

Choose a reason for hiding this comment

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

So, there's a really good example I can point to, but sadly, it was from Josh Comeau's Joy of React course, and that's pricey

A lot of the new official React documentation makes a lot of references to avoiding duplicate state, though. This section touches on it a little bit

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I see, so instead of objects we could use ids, is that right?

Copy link
Member

Choose a reason for hiding this comment

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

Right, maybe a Set isn't the right data structure, but the idea is that it would have nothing but IDs in it

@@ -345,8 +345,8 @@ dark = createTheme(dark, {
root: {
// It should be the same as the menu padding
"& .MuiDivider-root": {
marginTop: 4,
marginBottom: 4,
marginTop: `4px !important`,
Copy link
Member

Choose a reason for hiding this comment

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

Is this solving a bug, or is this more just a precaution?
I'm just worried about !important introducing specificity wars if any components ever need to override this

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Solving an issue. In this case, MUI is doing a very long chain to apply this style and I was not able to figure out how to make that happen here so I just used !important even not proud of that 😞

import { MONOSPACE_FONT_FAMILY } from "theme/constants";

export const useBatchActions = (options: {
onSuccess: () => Promise<void>;
Copy link
Member

Choose a reason for hiding this comment

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

I think this should be typed as () => (void | Promise<void>), just so components are free to use sync or async logic when it makes sense for them

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This component has a very specific use case and should only be used in one place so I would not try to make its interface generic to be re-used

props: BatchDeleteConfirmationProps,
) => {
const { checkedWorkspaces, open, onClose, onConfirm, isLoading } = props;
const [confirmation, setConfirmation] = useState({ value: "", error: false });
Copy link
Member

Choose a reason for hiding this comment

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

What values is value expected to have right now? So far, it looks like "" or DELETE?
I'm wondering if value could have its own type, if we're only going to be supporting a discrete set of operations

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It is a good idea but it does not work well for "dynamic" values since it can be whatever the user types and not only the "final" result. Makes sense? The values can be "D", "DE", "DEL", "DELE" or anything like "OTHER".

@MrPeacockNLB
Copy link
Contributor

Just a question from UX point of view. Is not the bottom left corner the default place for actions?

@BrunoQuaresma
Copy link
Collaborator Author

Just a question from UX point of view. Is not the bottom left corner the default place for actions?

I usually see it on the top right or left in a table when used to batch actions. 🤔

@BrunoQuaresma BrunoQuaresma changed the title feat(site): add stop and stop batch actions feat(site): add stop and start batch actions Nov 8, 2023
@BrunoQuaresma BrunoQuaresma merged commit 7f26111 into main Nov 8, 2023
@BrunoQuaresma BrunoQuaresma deleted the bq/start-stop-bulk-actions branch November 8, 2023 12:29
@github-actions github-actions bot locked and limited conversation to collaborators Nov 8, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants