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

Library Panels: Add library panel tab to share modal #32953

Merged
merged 2 commits into from
Apr 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React from 'react';
import { PanelModel } from 'app/features/dashboard/state';
import { AddLibraryPanelContents } from 'app/features/library-panels/components/AddLibraryPanelModal/AddLibraryPanelModal';

interface Props {
onDismiss?: () => void;
panel?: PanelModel;
initialFolderId?: number;
}

export const ShareGlobalPanel = ({ panel, initialFolderId, onDismiss }: Props) => {
if (!panel) {
return null;
}

return (
<div className="share-modal-body">
<div className="share-modal-header">
<div className="share-modal-content">
<p className="share-modal-info-text">Add this panel to the panel library.</p>
<AddLibraryPanelContents panel={panel} initialFolderId={initialFolderId} onDismiss={onDismiss!} />
</div>
</div>
</div>
);
};
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import React from 'react';
import { Modal, ModalTabsHeader, TabContent } from '@grafana/ui';
import { DashboardModel, PanelModel } from 'app/features/dashboard/state';
import { isPanelModelLibraryPanel } from 'app/features/library-panels/guard';
import { ShareLink } from './ShareLink';
import { ShareSnapshot } from './ShareSnapshot';
import { ShareExport } from './ShareExport';
import { ShareEmbed } from './ShareEmbed';
import { ShareModalTabModel } from './types';
import { contextSrv } from 'app/core/core';
import { ShareGlobalPanel } from './ShareGlobalPanel';

const customDashboardTabs: ShareModalTabModel[] = [];
const customPanelTabs: ShareModalTabModel[] = [];
Expand Down Expand Up @@ -38,6 +40,10 @@ function getTabs(props: Props) {

if (panel) {
tabs.push({ label: 'Embed', value: 'embed', component: ShareEmbed });

if (!isPanelModelLibraryPanel(panel)) {
tabs.push({ label: 'Global panel', value: 'global_panel', component: ShareGlobalPanel });
}
tabs.push(...customPanelTabs);
} else {
tabs.push({ label: 'Export', value: 'export', component: ShareExport });
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import React from 'react';
import { PanelModel } from '@grafana/data';
import { DashboardModel } from 'app/features/dashboard/state';
import { DashboardModel, PanelModel as InternalPanelModel } from 'app/features/dashboard/state';

export interface ShareModalTabProps {
dashboard: DashboardModel;
panel?: PanelModel;
onDismiss?(): void;
}

export type ShareModalTab = React.ComponentType<ShareModalTabProps>;
type ShareModalTabPropsWithInternalModel = ShareModalTabProps & { panel?: InternalPanelModel };
export type ShareModalTab =
| React.ComponentType<ShareModalTabProps>
| React.ComponentType<ShareModalTabPropsWithInternalModel>;
Comment on lines +11 to +14
Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm I wish we didn't need to reference the InternalPanelModel here, but I can see that would become hard to fix.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's a bit strange actually, looking at some of the other Share modal components (ShareSnapshot, ShareEmbed, and ShareExport) all use the internal PanelModel for their panel prop, while the ShareModalTab type seems to use the @grafana/data PanelModel interface. Not exactly sure why typescript didn't complain about that, but did for the component I've introduced with this PR, but I suspect it has something to do with the fact that the component I've introduced is a function component whereas the others are all class components.

Copy link
Contributor

Choose a reason for hiding this comment

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

That's fine let's get this merged.


export interface ShareModalTabModel {
label: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,20 @@ import { FolderPicker } from 'app/core/components/Select/FolderPicker';
import { PanelModel } from '../../../dashboard/state';
import { css } from '@emotion/css';
import { usePanelSave } from '../../utils/usePanelSave';

interface Props {
interface AddLibraryPanelContentsProps {
onDismiss: () => void;
isOpen?: boolean;
panel: PanelModel;
initialFolderId?: number;
}

export const AddLibraryPanelModal: React.FC<Props> = ({ isOpen = false, panel, initialFolderId, ...props }) => {
export const AddLibraryPanelContents = ({ panel, initialFolderId, onDismiss }: AddLibraryPanelContentsProps) => {
const styles = useStyles(getStyles);
const [folderId, setFolderId] = useState(initialFolderId);
const [panelTitle, setPanelTitle] = useState(panel.title);
const { saveLibraryPanel } = usePanelSave();

return (
<Modal title="Add this panel to the panel library" isOpen={isOpen} onDismiss={props.onDismiss}>
<>
<Field label="Library panel name">
<Input name="name" value={panelTitle} onChange={(e) => setPanelTitle(e.currentTarget.value)} />
</Field>
Expand All @@ -31,15 +29,27 @@ export const AddLibraryPanelModal: React.FC<Props> = ({ isOpen = false, panel, i
<Button
onClick={() => {
panel.title = panelTitle;
saveLibraryPanel(panel, folderId!).then(() => props.onDismiss());
saveLibraryPanel(panel, folderId!).then(() => onDismiss());
}}
>
Add panel to the panel library
</Button>
<Button variant="secondary" onClick={props.onDismiss}>
<Button variant="secondary" onClick={onDismiss}>
Cancel
</Button>
</div>
</>
);
};

interface Props extends AddLibraryPanelContentsProps {
isOpen?: boolean;
}

export const AddLibraryPanelModal: React.FC<Props> = ({ isOpen = false, panel, initialFolderId, ...props }) => {
return (
<Modal title="Add this panel to the panel library" isOpen={isOpen} onDismiss={props.onDismiss}>
<AddLibraryPanelContents panel={panel} initialFolderId={initialFolderId} onDismiss={props.onDismiss} />
</Modal>
);
};
Expand Down