123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141 |
- import { css, cx } from '@emotion/css';
- import React, { FC, useCallback } from 'react';
- import { useLocalStorage } from 'react-use';
- import { GrafanaTheme } from '@grafana/data';
- import { CollapsableSection, Icon, stylesFactory, useTheme } from '@grafana/ui';
- import { useUniqueId } from 'app/plugins/datasource/influxdb/components/useUniqueId';
- import { DashboardSection, OnToggleChecked } from '../types';
- import { getSectionIcon, getSectionStorageKey } from '../utils';
- import { SearchCheckbox } from './SearchCheckbox';
- interface SectionHeaderProps {
- editable?: boolean;
- onSectionClick: (section: DashboardSection) => void;
- onToggleChecked?: OnToggleChecked;
- section: DashboardSection;
- children: React.ReactNode;
- }
- export const SectionHeader: FC<SectionHeaderProps> = ({
- section,
- onSectionClick,
- children,
- onToggleChecked,
- editable = false,
- }) => {
- const theme = useTheme();
- const styles = getSectionHeaderStyles(theme, section.selected, editable);
- const setSectionExpanded = useLocalStorage(getSectionStorageKey(section.title), true)[1];
- const onSectionExpand = () => {
- setSectionExpanded(!section.expanded);
- onSectionClick(section);
- };
- const handleCheckboxClick = useCallback(
- (ev: React.MouseEvent) => {
- ev.stopPropagation();
- ev.preventDefault();
- onToggleChecked?.(section);
- },
- [onToggleChecked, section]
- );
- const id = useUniqueId();
- const labelId = `section-header-label-${id}`;
- return (
- <CollapsableSection
- isOpen={section.expanded ?? false}
- onToggle={onSectionExpand}
- className={styles.wrapper}
- contentClassName={styles.content}
- loading={section.itemsFetching}
- labelId={labelId}
- label={
- <>
- <SearchCheckbox
- className={styles.checkbox}
- editable={editable}
- checked={section.checked}
- onClick={handleCheckboxClick}
- aria-label="Select folder"
- />
- <div className={styles.icon}>
- <Icon name={getSectionIcon(section)} />
- </div>
- <div className={styles.text}>
- <span id={labelId}>{section.title}</span>
- {section.url && (
- <a href={section.url} className={styles.link}>
- <span className={styles.separator}>|</span> <Icon name="folder-upload" /> Go to folder
- </a>
- )}
- </div>
- </>
- }
- >
- {children}
- </CollapsableSection>
- );
- };
- const getSectionHeaderStyles = stylesFactory((theme: GrafanaTheme, selected = false, editable: boolean) => {
- const { sm } = theme.spacing;
- return {
- wrapper: cx(
- css`
- align-items: center;
- font-size: ${theme.typography.size.base};
- padding: 12px;
- border-bottom: none;
- color: ${theme.colors.textWeak};
- z-index: 1;
- &:hover,
- &.selected {
- color: ${theme.colors.text};
- }
- &:hover,
- &:focus-visible,
- &:focus-within {
- a {
- opacity: 1;
- }
- }
- `,
- 'pointer',
- { selected }
- ),
- checkbox: css`
- padding: 0 ${sm} 0 0;
- `,
- icon: css`
- padding: 0 ${sm} 0 ${editable ? 0 : sm};
- `,
- text: css`
- flex-grow: 1;
- line-height: 24px;
- `,
- link: css`
- padding: 2px 10px 0;
- color: ${theme.colors.textWeak};
- opacity: 0;
- transition: opacity 150ms ease-in-out;
- `,
- separator: css`
- margin-right: 6px;
- `,
- content: css`
- padding-top: 0px;
- padding-bottom: 0px;
- `,
- };
- });
|