2021-05-14 22:03:37 +08:00
|
|
|
import React, { useCallback, useEffect, useState } from 'react';
|
2022-04-22 21:33:13 +08:00
|
|
|
import { useAsync, useDebounce } from 'react-use';
|
|
|
|
|
2022-06-15 15:59:29 +08:00
|
|
|
import { isFetchError } from '@grafana/runtime';
|
2021-04-27 00:26:56 +08:00
|
|
|
import { Button, Field, Input, Modal } from '@grafana/ui';
|
2023-07-21 21:24:43 +08:00
|
|
|
import { OldFolderPicker } from 'app/core/components/Select/OldFolderPicker';
|
2022-10-06 23:34:04 +08:00
|
|
|
import { t, Trans } from 'app/core/internationalization';
|
2022-04-22 21:33:13 +08:00
|
|
|
|
2021-02-25 18:26:28 +08:00
|
|
|
import { PanelModel } from '../../../dashboard/state';
|
2021-05-14 22:03:37 +08:00
|
|
|
import { getLibraryPanelByName } from '../../state/api';
|
2022-04-22 21:33:13 +08:00
|
|
|
import { usePanelSave } from '../../utils/usePanelSave';
|
2021-05-14 22:03:37 +08:00
|
|
|
|
2021-04-15 15:29:34 +08:00
|
|
|
interface AddLibraryPanelContentsProps {
|
2021-02-25 18:26:28 +08:00
|
|
|
onDismiss: () => void;
|
|
|
|
panel: PanelModel;
|
2022-11-17 16:22:57 +08:00
|
|
|
initialFolderUid?: string;
|
2021-02-25 18:26:28 +08:00
|
|
|
}
|
|
|
|
|
2022-11-17 16:22:57 +08:00
|
|
|
export const AddLibraryPanelContents = ({ panel, initialFolderUid, onDismiss }: AddLibraryPanelContentsProps) => {
|
|
|
|
const [folderUid, setFolderUid] = useState(initialFolderUid);
|
2021-09-01 19:27:43 +08:00
|
|
|
const [panelName, setPanelName] = useState(panel.title);
|
|
|
|
const [debouncedPanelName, setDebouncedPanelName] = useState(panel.title);
|
2021-05-14 22:03:37 +08:00
|
|
|
const [waiting, setWaiting] = useState(false);
|
|
|
|
|
2021-09-01 19:27:43 +08:00
|
|
|
useEffect(() => setWaiting(true), [panelName]);
|
|
|
|
useDebounce(() => setDebouncedPanelName(panelName), 350, [panelName]);
|
2021-05-14 22:03:37 +08:00
|
|
|
|
2021-02-25 18:26:28 +08:00
|
|
|
const { saveLibraryPanel } = usePanelSave();
|
2021-05-14 22:03:37 +08:00
|
|
|
const onCreate = useCallback(() => {
|
2022-10-27 06:38:20 +08:00
|
|
|
panel.libraryPanel = { uid: '', name: panelName };
|
2022-11-17 16:22:57 +08:00
|
|
|
saveLibraryPanel(panel, folderUid!).then((res) => {
|
2021-05-14 22:03:37 +08:00
|
|
|
if (!(res instanceof Error)) {
|
|
|
|
onDismiss();
|
|
|
|
}
|
|
|
|
});
|
2022-11-17 16:22:57 +08:00
|
|
|
}, [panel, panelName, folderUid, onDismiss, saveLibraryPanel]);
|
2021-09-01 19:27:43 +08:00
|
|
|
const isValidName = useAsync(async () => {
|
2021-05-14 22:03:37 +08:00
|
|
|
try {
|
2022-11-17 16:22:57 +08:00
|
|
|
return !(await getLibraryPanelByName(panelName)).some((lp) => lp.folderUid === folderUid);
|
2021-05-14 22:03:37 +08:00
|
|
|
} catch (err) {
|
2022-06-15 15:59:29 +08:00
|
|
|
if (isFetchError(err)) {
|
|
|
|
err.isHandled = true;
|
|
|
|
}
|
2021-05-14 22:03:37 +08:00
|
|
|
return true;
|
|
|
|
} finally {
|
|
|
|
setWaiting(false);
|
|
|
|
}
|
2022-11-17 16:22:57 +08:00
|
|
|
}, [debouncedPanelName, folderUid]);
|
2021-05-14 22:03:37 +08:00
|
|
|
|
|
|
|
const invalidInput =
|
2021-09-01 19:27:43 +08:00
|
|
|
!isValidName?.value && isValidName.value !== undefined && panelName === debouncedPanelName && !waiting;
|
2021-02-25 18:26:28 +08:00
|
|
|
|
|
|
|
return (
|
2021-04-15 15:29:34 +08:00
|
|
|
<>
|
2021-05-14 22:03:37 +08:00
|
|
|
<Field
|
2022-10-06 23:34:04 +08:00
|
|
|
label={t('library-panel.add-modal.name', 'Library panel name')}
|
2021-05-14 22:03:37 +08:00
|
|
|
invalid={invalidInput}
|
2022-10-06 23:34:04 +08:00
|
|
|
error={invalidInput ? t('library-panel.add-modal.error', 'Library panel with this name already exists') : ''}
|
2021-05-14 22:03:37 +08:00
|
|
|
>
|
2021-10-14 13:13:15 +08:00
|
|
|
<Input
|
|
|
|
id="share-panel-library-panel-name-input"
|
|
|
|
name="name"
|
|
|
|
value={panelName}
|
|
|
|
onChange={(e) => setPanelName(e.currentTarget.value)}
|
|
|
|
/>
|
2021-02-25 18:26:28 +08:00
|
|
|
</Field>
|
2022-08-04 23:43:49 +08:00
|
|
|
<Field
|
2022-10-06 23:34:04 +08:00
|
|
|
label={t('library-panel.add-modal.folder', 'Save in folder')}
|
|
|
|
description={t(
|
|
|
|
'library-panel.add-modal.folder-description',
|
|
|
|
'Library panel permissions are derived from the folder permissions'
|
|
|
|
)}
|
2022-08-04 23:43:49 +08:00
|
|
|
>
|
2023-07-21 21:24:43 +08:00
|
|
|
<OldFolderPicker
|
2022-11-17 16:22:57 +08:00
|
|
|
onChange={({ uid }) => setFolderUid(uid)}
|
|
|
|
initialFolderUid={initialFolderUid}
|
2021-10-14 13:13:15 +08:00
|
|
|
inputId="share-panel-library-panel-folder-picker"
|
|
|
|
/>
|
2021-02-25 18:26:28 +08:00
|
|
|
</Field>
|
|
|
|
|
2021-04-27 00:26:56 +08:00
|
|
|
<Modal.ButtonRow>
|
2021-04-27 21:36:48 +08:00
|
|
|
<Button variant="secondary" onClick={onDismiss} fill="outline">
|
2022-10-06 23:34:04 +08:00
|
|
|
<Trans i18nKey="library-panel.add-modal.cancel">Cancel</Trans>
|
2021-04-27 21:36:48 +08:00
|
|
|
</Button>
|
2021-05-14 22:03:37 +08:00
|
|
|
<Button onClick={onCreate} disabled={invalidInput}>
|
2022-10-06 23:34:04 +08:00
|
|
|
<Trans i18nKey="library-panel.add-modal.create">Create library panel</Trans>
|
2021-02-25 18:26:28 +08:00
|
|
|
</Button>
|
2021-04-27 00:26:56 +08:00
|
|
|
</Modal.ButtonRow>
|
2021-04-15 15:29:34 +08:00
|
|
|
</>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
interface Props extends AddLibraryPanelContentsProps {
|
|
|
|
isOpen?: boolean;
|
|
|
|
}
|
|
|
|
|
2022-11-17 16:22:57 +08:00
|
|
|
export const AddLibraryPanelModal = ({ isOpen = false, panel, initialFolderUid, ...props }: Props) => {
|
2021-04-15 15:29:34 +08:00
|
|
|
return (
|
2021-05-04 16:00:44 +08:00
|
|
|
<Modal title="Create library panel" isOpen={isOpen} onDismiss={props.onDismiss}>
|
2022-11-17 16:22:57 +08:00
|
|
|
<AddLibraryPanelContents panel={panel} initialFolderUid={initialFolderUid} onDismiss={props.onDismiss} />
|
2021-02-25 18:26:28 +08:00
|
|
|
</Modal>
|
|
|
|
);
|
|
|
|
};
|