Add Loading Spinner API to content action overflow menu extension point

This commit is contained in:
Thomas Zerr
2023-09-18 10:04:03 +02:00
parent afbb14239e
commit aa767ec945
5 changed files with 30 additions and 6 deletions

View File

@@ -0,0 +1,2 @@
- type: changed
description: The internal API for content action menus were changed, to handle loading states of extensions

View File

@@ -640,6 +640,7 @@ export type ContentActionExtensionProps = {
revision: string;
handleExtensionError: React.Dispatch<React.SetStateAction<Error | undefined>>;
contentType?: ContentType;
setLoading?: (isLoading: boolean) => void;
};
type BaseActionBarOverflowMenuProps = {

View File

@@ -23,19 +23,25 @@
*/
import { binder, extensionPoints } from "@scm-manager/ui-extensions";
import React, { FC, ReactElement, useState } from "react";
import React, { FC, ReactElement, useCallback, useState } from "react";
import styled from "styled-components";
import { Menu } from "@scm-manager/ui-overlays";
import FallbackMenuButton from "./FallbackMenuButton";
import MenuItem from "./MenuItem";
import { Icon } from "@scm-manager/ui-buttons";
import { Button, Icon } from "@scm-manager/ui-buttons";
import { useTranslation } from "react-i18next";
import { SmallLoadingSpinner } from "@scm-manager/ui-components";
const HR = styled.hr`
margin: 0.25rem;
background: var(--scm-border-color);
`;
const StyledLoadingButton = styled(Button)`
padding-left: 1rem;
padding-right: 1rem;
`;
type Props = {
extensionProps: extensionPoints.ContentActionExtensionProps;
};
@@ -47,6 +53,13 @@ const ContentActionMenu: FC<Props> = ({ extensionProps }) => {
"repos.sources.content.actionbar.menu",
extensionProps
);
const [loadingExtension, setLoadingExtensions] = useState<Record<string, boolean>>({});
const setLoading = useCallback((isLoading: boolean, extension: string) => {
setLoadingExtensions((prevState) => ({ ...prevState, [extension]: isLoading }));
}, []);
const categories = extensions.reduce<Record<string, extensionPoints.FileViewActionBarOverflowMenu["type"][]>>(
(result, extension) => {
if (!(extension.category in result)) {
@@ -64,7 +77,11 @@ const ContentActionMenu: FC<Props> = ({ extensionProps }) => {
return (
<>
{extensions.length === 1 ? (
{Object.values(loadingExtension).some((isLoading) => isLoading) ? (
<StyledLoadingButton>
<SmallLoadingSpinner />
</StyledLoadingButton>
) : extensions.length === 1 ? (
<FallbackMenuButton
extension={extensions[0]}
extensionProps={extensionProps}
@@ -88,6 +105,7 @@ const ContentActionMenu: FC<Props> = ({ extensionProps }) => {
key={extension.label}
extensionProps={extensionProps}
setSelectedModal={setSelectedModal}
setLoading={(isLoading: boolean) => setLoading(isLoading, extension.label)}
{...extension}
/>
))}

View File

@@ -32,8 +32,9 @@ const MenuItem: FC<
extensionPoints.FileViewActionBarOverflowMenu["type"] & {
setSelectedModal: (element: ReactElement | undefined) => void;
extensionProps: extensionPoints.ContentActionExtensionProps;
setLoading?: (isLoading: boolean) => void;
}
> = ({ extensionProps, label, icon, props, category, setSelectedModal, ...rest }) => {
> = ({ extensionProps, label, icon, props, category, setSelectedModal, setLoading, ...rest }) => {
if ("action" in rest) {
return (
<ActionMenuItem
@@ -66,6 +67,7 @@ const MenuItem: FC<
icon={icon}
extensionProps={extensionProps}
setSelectedModal={setSelectedModal}
setLoading={setLoading}
props={props}
{...rest}
/>

View File

@@ -32,15 +32,16 @@ const ModalMenuItem: FC<
extensionPoints.ModalMenuProps & {
setSelectedModal: (element: ReactElement | undefined) => void;
extensionProps: extensionPoints.ContentActionExtensionProps;
setLoading?: (isLoading: boolean) => void;
}
> = ({ modalElement, label, icon, props, extensionProps, setSelectedModal }) => {
> = ({ modalElement, label, icon, props, extensionProps, setSelectedModal, setLoading }) => {
const [t] = useTranslation("plugins");
return (
<Menu.Button
onSelect={() =>
setSelectedModal(
React.createElement(modalElement, { ...extensionProps, close: () => setSelectedModal(undefined) })
React.createElement(modalElement, { ...extensionProps, close: () => setSelectedModal(undefined), setLoading })
)
}
{...props}