@grafana/ui: Replace various icons using Icon component (#23442)

* Replace icons in dashboard and settings

* Replace icons in alerting

* Update batch of icons

* Implement icons accross various files

* Style updates

* Search: Fix recent and starred icons

* Update styling and details

* Replace new icon created by unicons

* Fix e2e test, styling

* Minor styling updates

Co-authored-by: Clarity-89 <homes89@ukr.net>
pull/23522/head
Ivana Huckova 5 years ago committed by GitHub
parent 0aa95d97c8
commit 1c58202b26
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      packages/grafana-ui/src/components/AlphaNotice/AlphaNotice.tsx
  2. 2
      packages/grafana-ui/src/components/Button/Button.story.tsx
  3. 2
      packages/grafana-ui/src/components/ButtonCascader/ButtonCascader.tsx
  4. 8
      packages/grafana-ui/src/components/Cascader/Cascader.tsx
  5. 9
      packages/grafana-ui/src/components/ContextMenu/ContextMenu.tsx
  6. 3
      packages/grafana-ui/src/components/DataLinks/DataLinkEditor.tsx
  7. 3
      packages/grafana-ui/src/components/DataSourceSettings/CustomHeadersSettings.tsx
  8. 3
      packages/grafana-ui/src/components/DataSourceSettings/DataSourceHttpSettings.tsx
  9. 3
      packages/grafana-ui/src/components/Drawer/Drawer.tsx
  10. 2
      packages/grafana-ui/src/components/FormLabel/FormLabel.tsx
  11. 3
      packages/grafana-ui/src/components/Forms/FieldValidationMessage.tsx
  12. 2
      packages/grafana-ui/src/components/Forms/Legacy/Select/ButtonSelect.story.internal.tsx
  13. 3
      packages/grafana-ui/src/components/Forms/Legacy/Select/ButtonSelect.tsx
  14. 5
      packages/grafana-ui/src/components/Forms/Legacy/Select/IndicatorsContainer.tsx
  15. 3
      packages/grafana-ui/src/components/Forms/Legacy/Select/SelectOption.tsx
  16. 4
      packages/grafana-ui/src/components/Forms/Legacy/Select/_Select.scss
  17. 6
      packages/grafana-ui/src/components/Icon/Icon.tsx
  18. 17
      packages/grafana-ui/src/components/Icon/assets/Circle.tsx
  19. 1
      packages/grafana-ui/src/components/Icon/assets/index.ts
  20. 1
      packages/grafana-ui/src/components/Input/Input.tsx
  21. 13
      packages/grafana-ui/src/components/Legend/LegendTable.tsx
  22. 4
      packages/grafana-ui/src/components/Legend/SeriesIcon.tsx
  23. 3
      packages/grafana-ui/src/components/LoadingPlaceholder/LoadingPlaceholder.tsx
  24. 3
      packages/grafana-ui/src/components/Modal/Modal.story.tsx
  25. 2
      packages/grafana-ui/src/components/PanelOptionsGroup/PanelOptionsGroup.tsx
  26. 3
      packages/grafana-ui/src/components/Segment/Segment.story.tsx
  27. 3
      packages/grafana-ui/src/components/Segment/SegmentAsync.story.tsx
  28. 3
      packages/grafana-ui/src/components/Segment/SegmentInput.story.tsx
  29. 2
      packages/grafana-ui/src/components/Select/SelectBase.tsx
  30. 6
      packages/grafana-ui/src/components/Select/SelectOptionGroup.tsx
  31. 3
      packages/grafana-ui/src/components/Spinner/Spinner.tsx
  32. 3
      packages/grafana-ui/src/components/TableInputCSV/TableInputCSV.tsx
  33. 12
      packages/grafana-ui/src/components/TagsInput/TagItem.tsx
  34. 13
      packages/grafana-ui/src/components/TimePicker/TimePickerContent/TimePickerCalendar.tsx
  35. 3
      packages/grafana-ui/src/components/TimePicker/TimePickerContent/TimeRangeOption.tsx
  36. 15
      packages/grafana-ui/src/components/TransformersUI/FilterByNameTransformerEditor.tsx
  37. 15
      packages/grafana-ui/src/components/TransformersUI/FilterByRefIdTransformerEditor.tsx
  38. 101
      packages/grafana-ui/src/types/icon.ts
  39. 2
      packages/grafana-ui/src/utils/dataLinks.ts
  40. 8
      pkg/components/dashdiffs/formatter_basic.go
  41. 4
      plugins-bundled/internal/input-datasource/src/InputQueryEditor.tsx
  42. 2
      public/app/core/components/EmptyListCTA/EmptyListCTA.tsx
  43. 5
      public/app/core/components/Footer/Footer.tsx
  44. 4
      public/app/core/components/PageHeader/PageHeader.test.tsx
  45. 4
      public/app/core/components/PermissionList/PermissionListItem.tsx
  46. 24
      public/app/core/components/Select/__snapshots__/TeamPicker.test.tsx.snap
  47. 24
      public/app/core/components/Select/__snapshots__/UserPicker.test.tsx.snap
  48. 4
      public/app/core/components/help/HelpModal.tsx
  49. 2
      public/app/core/components/manage_dashboards/manage_dashboards.html
  50. 2
      public/app/core/components/manage_dashboards/manage_dashboards.ts
  51. 2
      public/app/core/components/search/search_results.html
  52. 3
      public/app/core/components/sidemenu/SignIn.tsx
  53. 4
      public/app/core/components/sidemenu/__snapshots__/SignIn.test.tsx.snap
  54. 6
      public/app/core/copy/appNotification.ts
  55. 2
      public/app/core/nav_model_srv.ts
  56. 2
      public/app/core/selectors/navModel.ts
  57. 4
      public/app/core/services/search_srv.ts
  58. 2
      public/app/core/services/util_srv.ts
  59. 12
      public/app/core/specs/manage_dashboards.test.ts
  60. 2
      public/app/features/admin/AdminEditUserCtrl.ts
  61. 2
      public/app/features/admin/AdminListOrgsCtrl.ts
  62. 3
      public/app/features/admin/UserSyncInfo.tsx
  63. 6
      public/app/features/admin/ldap/LdapConnectionStatus.tsx
  64. 3
      public/app/features/admin/ldap/LdapSyncInfo.tsx
  65. 6
      public/app/features/admin/ldap/LdapUserGroups.tsx
  66. 4
      public/app/features/admin/ldap/LdapUserPermissions.tsx
  67. 4
      public/app/features/admin/ldap/LdapUserTeams.tsx
  68. 2
      public/app/features/admin/partials/edit_org.html
  69. 2
      public/app/features/admin/partials/edit_user.html
  70. 2
      public/app/features/admin/partials/orgs.html
  71. 18
      public/app/features/alerting/AlertTabCtrl.ts
  72. 7
      public/app/features/alerting/StateHistory.tsx
  73. 8
      public/app/features/alerting/TestRuleResult.tsx
  74. 2
      public/app/features/alerting/partials/alert_howto.html
  75. 18
      public/app/features/alerting/partials/alert_tab.html
  76. 2
      public/app/features/alerting/partials/notifications_list.html
  77. 2
      public/app/features/alerting/state/alertDef.ts
  78. 2
      public/app/features/alerting/state/reducers.test.ts
  79. 2
      public/app/features/annotations/editor_ctrl.ts
  80. 14
      public/app/features/annotations/partials/editor.html
  81. 2
      public/app/features/api-keys/ApiKeysAddedModal.tsx
  82. 1
      public/app/features/api-keys/__snapshots__/ApiKeysAddedModal.test.tsx.snap
  83. 4
      public/app/features/dashboard/components/DashLinks/DashLinksContainerCtrl.ts
  84. 2
      public/app/features/dashboard/components/DashLinks/DashLinksEditorCtrl.ts
  85. 12
      public/app/features/dashboard/components/DashLinks/editor.html
  86. 7
      public/app/features/dashboard/components/DashNav/DashNav.tsx
  87. 12
      public/app/features/dashboard/components/DashboardRow/DashboardRow.tsx
  88. 22
      public/app/features/dashboard/components/DashboardSettings/SettingsCtrl.ts
  89. 2
      public/app/features/dashboard/components/DashboardSettings/template.html
  90. 2
      public/app/features/dashboard/components/RowOptions/template.html
  91. 2
      public/app/features/dashboard/components/ShareModal/ShareLink.tsx
  92. 4
      public/app/features/dashboard/components/ShareModal/ShareSnapshot.tsx
  93. 2
      public/app/features/dashboard/components/UnsavedChangesModal/UnsavedChangesModalCtrl.ts
  94. 90
      public/app/features/dashboard/components/VersionHistory/template.html
  95. 4
      public/app/features/dashboard/containers/DashboardPage.tsx
  96. 5
      public/app/features/dashboard/containers/__snapshots__/DashboardPage.test.tsx.snap
  97. 1
      public/app/features/dashboard/dashgrid/PanelChromeAngular.tsx
  98. 14
      public/app/features/dashboard/dashgrid/PanelHeader/PanelHeader.tsx
  99. 4
      public/app/features/dashboard/panel_editor/EditorTabBody.tsx
  100. 2
      public/app/features/dashboard/panel_editor/QueriesTab.tsx
  101. Some files were not shown because too many files have changed in this diff Show More

@ -2,6 +2,7 @@ import React, { FC, useContext } from 'react';
import { css, cx } from 'emotion';
import { ThemeContext } from '../../index';
import { PluginState } from '@grafana/data';
import { Icon } from '../Icon/Icon';
interface Props {
state?: PluginState;
@ -30,7 +31,7 @@ export const AlphaNotice: FC<Props> = ({ state, text, className }) => {
return (
<div className={styles} title={tooltipContent}>
<i className="fa fa-warning" /> {state}
<Icon name="exclamation-triangle" /> {state}
</div>
);
};

@ -28,7 +28,7 @@ export const simple = () => {
const icon = getIconKnob();
return (
<Button variant={variant as ButtonVariant} size={size as ComponentSize} icon={icon && `fa fa-${icon}`}>
<Button variant={variant as ButtonVariant} size={size as ComponentSize} icon={icon}>
{buttonText}
</Button>
);

@ -40,7 +40,7 @@ export const ButtonCascader: React.FC<ButtonCascaderProps> = props => {
expandIcon={null}
>
<button className="gf-form-label gf-form-label--btn" disabled={props.disabled}>
{props.children} <Icon name="angle-down" />
{props.children} <Icon name="angle-down" style={{ marginBottom: 0, marginLeft: '4px' }} />
</button>
</RCCascader>
);

@ -212,7 +212,13 @@ export class Cascader extends React.PureComponent<CascaderProps, CascaderState>
value={activeLabel}
onKeyDown={this.onInputKeyDown}
onChange={() => {}}
suffix={focusCascade ? <Icon name="angle-up" /> : <Icon name="angle-down" />}
suffix={
focusCascade ? (
<Icon name="angle-up" />
) : (
<Icon name="angle-down" style={{ marginBottom: 0, marginLeft: '4px' }} />
)
}
/>
</div>
</RCCascader>

@ -5,6 +5,8 @@ import { selectThemeVariant, ThemeContext } from '../../index';
import { GrafanaTheme } from '@grafana/data';
import { stylesFactory } from '../../themes/stylesFactory';
import { Portal, List } from '../index';
import { Icon } from '../Icon/Icon';
import { IconName } from '../../types';
import { LinkTarget } from '@grafana/data';
export interface ContextMenuItem {
@ -140,13 +142,8 @@ const getContextMenuStyles = stylesFactory((theme: GrafanaTheme) => {
`,
icon: css`
opacity: 0.7;
width: 12px;
height: 12px;
display: inline-block;
margin-right: 10px;
color: ${theme.colors.linkDisabled};
position: relative;
top: 4px;
`,
};
});
@ -226,7 +223,7 @@ const ContextMenuItem: React.FC<ContextMenuItemProps> = React.memo(
}
}}
>
{icon && <i className={cx(`${icon}`, styles.icon)} />} {label}
{icon && <Icon name={icon as IconName} className={styles.icon} />} {label}
</a>
</div>
);

@ -5,6 +5,7 @@ import { Switch } from '../Switch/Switch';
import { css } from 'emotion';
import { ThemeContext, stylesFactory } from '../../themes/index';
import { DataLinkInput } from './DataLinkInput';
import { Icon } from '../Icon/Icon';
interface DataLinkEditorProps {
index: number;
@ -60,7 +61,7 @@ export const DataLinkEditor: React.FC<DataLinkEditorProps> = React.memo(
/>
<Switch label="Open in new tab" checked={value.targetBlank || false} onChange={onOpenInNewTabChanged} />
<button className="gf-form-label gf-form-label--btn" onClick={onRemoveClick} title="Remove link">
<i className="fa fa-times" />
<Icon name="times" />
</button>
</div>
<FormField

@ -4,6 +4,7 @@ import uniqueId from 'lodash/uniqueId';
import { DataSourceSettings } from '@grafana/data';
import { Button } from '../Button';
import { FormField } from '../FormField/FormField';
import { Icon } from '../Icon/Icon';
import { SecretFormField } from '../SecretFormField/SecretFormField';
import { stylesFactory } from '../../themes';
@ -77,7 +78,7 @@ const CustomHeaderRow: React.FC<CustomHeaderRowProps> = ({ header, onBlur, onCha
onBlur={onBlur}
/>
<Button variant="secondary" size="xs" onClick={_e => onRemove(header.id)}>
<i className="fa fa-trash" />
<Icon name="trash-alt" />
</Button>
</div>
);

@ -10,6 +10,7 @@ import { HttpSettingsProps } from './types';
import { CustomHeadersSettings } from './CustomHeadersSettings';
import { Select } from '../Forms/Legacy/Select/Select';
import { Input } from '../Forms/Legacy/Input/Input';
import { Icon } from '../Icon/Icon';
import { FormField } from '../FormField/FormField';
import { FormLabel } from '../FormLabel/FormLabel';
import { Switch } from '../Switch/Switch';
@ -139,7 +140,7 @@ export const DataSourceHttpSettings: React.FC<HttpSettingsProps> = props => {
onClick={() => setIsAccessHelpVisible(isVisible => !isVisible)}
>
Help&nbsp;
<i className={`fa fa-caret-${isAccessHelpVisible ? 'down' : 'right'}`} />
<Icon name={isAccessHelpVisible ? 'angle-down' : 'angle-right'} />
</label>
</div>
</div>

@ -3,6 +3,7 @@ import { GrafanaTheme } from '@grafana/data';
import RcDrawer from 'rc-drawer';
import { css } from 'emotion';
import CustomScrollbar from '../CustomScrollbar/CustomScrollbar';
import { Icon } from '../Icon/Icon';
import { stylesFactory, useTheme } from '../../themes';
export interface Props {
@ -93,7 +94,7 @@ export const Drawer: FC<Props> = ({
<div className={drawerStyles.titleWrapper}>
<div>{title}</div>
<div className={drawerStyles.close} onClick={onClose}>
<i className="fa fa-close" />
<Icon name="times" />
</div>
</div>
)}

@ -34,7 +34,7 @@ export const FormLabel: FunctionComponent<Props> = ({
{tooltip && (
<Tooltip placement="top" content={tooltip} theme={'info'}>
<div className="gf-form-help-icon gf-form-help-icon--right-normal">
<Icon name="info-circle" size="sm" style={{ marginBottom: 0 }} />
<Icon name="info-circle" size="xs" style={{ marginLeft: '10px' }} />
</div>
</Tooltip>
)}

@ -2,6 +2,7 @@ import React from 'react';
import { useTheme, stylesFactory } from '../../themes';
import { GrafanaTheme } from '@grafana/data';
import { css, cx } from 'emotion';
import { Icon } from '../Icon/Icon';
export interface FieldValidationMessageProps {
children: string;
@ -45,7 +46,7 @@ export const FieldValidationMessage: React.FC<FieldValidationMessageProps> = ({
return (
<div className={cx(styles.fieldValidationMessage, className)}>
<i className={cx(styles.fieldValidationMessageIcon, 'fa', 'fa-warning')} />
<Icon className={styles.fieldValidationMessageIcon} name="exclamation-triangle" />
{children}
</div>
);

@ -32,7 +32,7 @@ ButtonSelectStories.add('default', () => {
}}
label={value.label ? value.label : ''}
className="refresh-select"
iconClass={text('iconClass', 'fa fa-clock-o fa-fw')}
iconClass={text('iconClass', 'clock-nine')}
/>
);
}}

@ -2,6 +2,7 @@ import React, { PureComponent, ReactElement } from 'react';
import Select from './Select';
import { PopoverContent } from '../../../Tooltip/Tooltip';
import { Icon } from '../../../Icon/Icon';
import { IconName } from '../../../../types';
import { SelectableValue } from '@grafana/data';
interface ButtonComponentProps {
@ -22,7 +23,7 @@ const ButtonComponent = (buttonProps: ButtonComponentProps) => (props: any) => {
tabIndex={0} // necessary to get onBlur to work https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#Clicking_and_focus
>
<div className="select-button">
{iconClass && <i className={`select-button-icon ${iconClass}`} />}
{iconClass && <Icon className={'select-button-icon'} name={iconClass as IconName} />}
<span className="select-button-value">{label ? label : ''}</span>
{!props.menuIsOpen && <Icon name="angle-down" style={{ marginBottom: 0 }} size="lg" />}
{props.menuIsOpen && <Icon name="angle-up" style={{ marginBottom: 0 }} size="lg" />}

@ -1,4 +1,5 @@
import React from 'react';
import { Icon } from '../../../Icon/Icon';
// Ignoring because I couldn't get @types/react-select work wih Torkel's fork
// @ts-ignore
@ -8,9 +9,7 @@ export const IndicatorsContainer = (props: any) => {
const isOpen = props.selectProps.menuIsOpen;
return (
<components.IndicatorsContainer {...props}>
<span
className={`gf-form-select-box__select-arrow ${isOpen ? `gf-form-select-box__select-arrow--reversed` : ''}`}
/>
<Icon name={isOpen ? 'angle-up' : 'angle-down'} style={{ marginTop: '7px' }} />
</components.IndicatorsContainer>
);
};

@ -1,4 +1,5 @@
import React from 'react';
import { Icon } from '../../../Icon/Icon';
// Ignoring because I couldn't get @types/react-select work wih Torkel's fork
// @ts-ignore
@ -24,7 +25,7 @@ export const SelectOption = (props: ExtendedOptionProps) => {
<div>{children}</div>
{data.description && <div className="gf-form-select-box__desc-option__desc">{data.description}</div>}
</div>
{isSelected && <i className="fa fa-check" aria-hidden="true" />}
{isSelected && <Icon name="check" aria-hidden="true" />}
</div>
</components.Option>
);

@ -43,8 +43,6 @@ $select-input-bg-disabled: $input-bg-disabled;
}
.gf-form-select-box__input {
padding-left: 5px;
input {
line-height: inherit;
}
@ -122,7 +120,7 @@ $select-input-bg-disabled: $input-bg-disabled;
.gf-form-select-box__value-container {
display: inline-block;
padding: 6px 16px 6px 10px;
padding: 6px 20px 6px 10px;
vertical-align: middle;
> div {

@ -8,6 +8,8 @@ import { IconName, IconType, IconSize } from '../../types/icon';
import * as DefaultIcon from '@iconscout/react-unicons';
import * as MonoIcon from './assets';
const alwaysMonoIcons = ['grafana', 'favorite'];
interface IconProps extends React.HTMLAttributes<HTMLDivElement> {
name: IconName;
size?: IconSize;
@ -43,6 +45,10 @@ export const Icon = React.forwardRef<HTMLDivElement, IconProps>(
return <i className={cx(name, className)} {...divElementProps} style={style} />;
}
if (alwaysMonoIcons.includes(name)) {
type = 'mono';
}
const iconName = type === 'default' ? `Uil${toPascalCase(name)}` : toPascalCase(name);
/* Unicons don't have type definitions */

@ -0,0 +1,17 @@
import React, { FunctionComponent } from 'react';
import { SvgProps } from './types';
export const Circle: FunctionComponent<SvgProps> = ({ size, ...rest }) => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
enableBackground="new 0 0 24 24"
viewBox="0 0 24 24"
width={size}
height={size}
{...rest}
>
<circle cx="12" cy="12" r="10" />
</svg>
);
};

@ -9,3 +9,4 @@ export * from './FolderPlus';
export * from './Folder';
export * from './Import';
export * from './PanelAdd';
export * from './Circle';

@ -197,6 +197,7 @@ export const getInputStyles = stylesFactory(({ theme, invalid = false }: StyleDe
label: input-suffix;
padding-right: ${theme.spacing.sm};
padding-left: ${theme.spacing.xs};
margin-bottom: -2px;
border-left: none;
border-top-left-radius: 0;
border-bottom-left-radius: 0;

@ -1,6 +1,7 @@
import React, { useContext } from 'react';
import { css, cx } from 'emotion';
import { LegendComponentProps } from './Legend';
import { Icon } from '../Icon/Icon';
import { ThemeContext } from '../../themes/ThemeContext';
interface LegendTableProps extends LegendComponentProps {
@ -53,13 +54,11 @@ export const LegendTable: React.FunctionComponent<LegendTableProps> = ({
>
{columnHeader}
{sortBy === columnHeader && (
<span
className={cx(
`fa fa-caret-${sortDesc ? 'down' : 'up'}`,
css`
margin-left: ${theme.spacing.sm};
`
)}
<Icon
className={css`
margin-left: ${theme.spacing.sm};
`}
name={sortDesc ? 'angle-down' : 'angle-up'}
/>
)}
</th>

@ -1,5 +1,5 @@
import React from 'react';
import { cx } from 'emotion';
import { Icon } from '../Icon/Icon';
export interface SeriesIconProps {
color: string;
@ -7,7 +7,7 @@ export interface SeriesIconProps {
}
export const SeriesIcon: React.FunctionComponent<SeriesIconProps> = ({ color, className }) => {
return <i className={cx('fa', 'fa-minus', className)} style={{ color }} />;
return <Icon name="minus" className={className} style={{ color }} />;
};
SeriesIcon.displayName = 'SeriesIcon';

@ -1,4 +1,5 @@
import React, { SFC } from 'react';
import { Icon } from '../Icon/Icon';
interface LoadingPlaceholderProps {
text: string;
@ -6,6 +7,6 @@ interface LoadingPlaceholderProps {
export const LoadingPlaceholder: SFC<LoadingPlaceholderProps> = ({ text }) => (
<div className="gf-form-group">
{text} <i className="fa fa-spinner fa-spin" />
{text} <Icon name="fa fa-spinner" className="fa-spin" />
</div>
);

@ -5,6 +5,7 @@ import { text, boolean } from '@storybook/addon-knobs';
import { withCenteredStory } from '../../utils/storybook/withCenteredStory';
import { UseState } from '../../utils/storybook/UseState';
import { Modal } from './Modal';
import { Icon } from '../Icon/Icon';
import { ModalTabsHeader } from './ModalTabsHeader';
import { TabContent } from '../Tabs/TabContent';
@ -35,7 +36,7 @@ ModalStories.add('default', () => {
<Modal
title={
<div className="modal-header-title">
<i className="fa fa-exclamation-triangle" />
<Icon name="exclamation-triangle" size="lg" />
<span className="p-l-1">My Modal</span>
</div>
}

@ -16,7 +16,7 @@ export const PanelOptionsGroup: FunctionComponent<Props> = props => {
<div className="panel-options-group__header">
<button className="panel-options-group__add-btn" onClick={props.onAdd}>
<div className="panel-options-group__add-circle">
<i className="fa fa-plus" />
<Icon name="plus-circle" />
</div>
<span className="panel-options-group__title">{props.title}</span>
</button>

@ -1,10 +1,11 @@
import React, { useState } from 'react';
import { action } from '@storybook/addon-actions';
import { Segment } from './';
import { Icon } from '../Icon/Icon';
const AddButton = (
<a className="gf-form-label query-part">
<i className="fa fa-plus" />
<Icon name="plus-circle" />
</a>
);

@ -2,10 +2,11 @@ import React, { useState } from 'react';
import { action } from '@storybook/addon-actions';
import { SelectableValue } from '@grafana/data';
import { SegmentAsync } from './';
import { Icon } from '../Icon/Icon';
const AddButton = (
<a className="gf-form-label query-part">
<i className="fa fa-plus" />
<Icon name="plus-circle" />
</a>
);

@ -1,6 +1,7 @@
import React, { useState } from 'react';
import { action } from '@storybook/addon-actions';
import { SegmentInput } from '.';
import { Icon } from '../Icon/Icon';
const SegmentFrame = ({ children }: any) => (
<>
@ -77,7 +78,7 @@ export const InputWithAutoFocus = () => {
setInputComponents([...inputComponents, InputComponent]);
}}
>
<i className="fa fa-plus" />
<Icon name="plus-circle" />
</a>
</SegmentFrame>
);

@ -243,7 +243,7 @@ export function SelectBase<T>({
);
},
LoadingIndicator: (props: any) => {
return <i className="fa fa-spinner fa-spin" />;
return <Icon className="fa-spin" name="fa fa-spinner" />;
},
LoadingMessage: (props: any) => {
return <div className={styles.loadingMessage}>{loadingMessage}</div>;

@ -1,9 +1,10 @@
import React, { PureComponent } from 'react';
import { css, cx } from 'emotion';
import { css } from 'emotion';
import { GrafanaTheme } from '@grafana/data';
import { GroupProps } from 'react-select';
import { stylesFactory, withTheme, selectThemeVariant } from '../../themes';
import { Themeable } from '../../types';
import { Icon } from '../Icon/Icon';
interface ExtendedGroupProps extends GroupProps<any>, Themeable {
data: {
@ -79,12 +80,11 @@ class UnthemedSelectOptionGroup extends PureComponent<ExtendedGroupProps, State>
const { children, label, theme } = this.props;
const { expanded } = this.state;
const styles = getSelectOptionGroupStyles(theme);
const icon = expanded ? 'fa-caret-left' : 'fa-caret-down';
return (
<div>
<div className={styles.header} onClick={this.onToggleChildren}>
<span className={styles.label}>{label}</span>
<i className={cx('fa', icon, styles.icon)} />{' '}
<Icon className={styles.icon} name={expanded ? 'angle-left' : 'angle-down'} />{' '}
</div>
{expanded && children}
</div>

@ -1,6 +1,7 @@
import React, { FC } from 'react';
import { cx, css } from 'emotion';
import { stylesFactory } from '../../themes';
import { Icon } from '../Icon/Icon';
const getStyles = stylesFactory((size: number, inline: boolean) => {
return {
@ -27,7 +28,7 @@ export const Spinner: FC<Props> = (props: Props) => {
const styles = getStyles(size, inline);
return (
<div style={style} className={cx(styles.wrapper, className)}>
<i className={cx('fa fa-spinner fa-spin', iconClassName)} />
<Icon className={cx('fa-spin', iconClassName)} name="fa fa-spinner" />
</div>
);
};

@ -1,6 +1,7 @@
import React from 'react';
import debounce from 'lodash/debounce';
import { DataFrame, CSVConfig, readCSV } from '@grafana/data';
import { Icon } from '../Icon/Icon';
interface Props {
config?: CSVConfig;
@ -75,7 +76,7 @@ export class TableInputCSV extends React.PureComponent<Props, State> {
return (
<span key={index}>
Rows:{frame.length}, Columns:{frame.fields.length} &nbsp;
<i className="fa fa-check-circle" />
<Icon name="check-circle" />
</span>
);
})}

@ -1,7 +1,8 @@
import React, { FC } from 'react';
import { css, cx } from 'emotion';
import { css } from 'emotion';
import { getTagColorsFromName } from '../../utils';
import { stylesFactory, useTheme } from '../../themes';
import { Icon } from '../Icon/Icon';
import { GrafanaTheme } from '@grafana/data';
interface Props {
@ -32,13 +33,6 @@ const getStyles = stylesFactory(({ theme, name }: { theme: GrafanaTheme; name: s
nameStyle: css`
margin-right: 3px;
`,
removeStyle: cx([
'fa fa-times',
css`
cursor: pointer;
`,
]),
};
});
@ -49,7 +43,7 @@ export const TagItem: FC<Props> = ({ name, onRemove }) => {
return (
<div className={styles.itemStyle}>
<span className={styles.nameStyle}>{name}</span>
<i className={styles.removeStyle} onClick={() => onRemove(name)} />
<Icon name="times" onClick={() => onRemove(name)} />
</div>
);
};

@ -1,11 +1,12 @@
import React, { memo, useState, useEffect } from 'react';
import { css, cx } from 'emotion';
import { css } from 'emotion';
import Calendar from 'react-calendar/dist/entry.nostyle';
import { GrafanaTheme, dateTime, TIME_FORMAT } from '@grafana/data';
import { stringToDateTimeType } from '../time';
import { useTheme, stylesFactory } from '../../../themes';
import { TimePickerTitle } from './TimePickerTitle';
import { Button } from '../../Button';
import { Icon } from '../../Icon/Icon';
import { Portal } from '../../Portal/Portal';
import { getThemeColors } from './colors';
import { ClickOutsideWrapper } from '../../ClickOutsideWrapper/ClickOutsideWrapper';
@ -186,10 +187,6 @@ const getHeaderStyles = stylesFactory((theme: GrafanaTheme) => {
justify-content: space-between;
padding: 7px;
`,
close: css`
cursor: pointer;
font-size: ${theme.typography.size.lg};
`,
};
});
@ -245,7 +242,7 @@ const Header = memo<Props>(({ onClose }) => {
return (
<div className={styles.container}>
<TimePickerTitle>Select a time range</TimePickerTitle>
<i className={cx(styles.close, 'fa', 'fa-times')} onClick={onClose} />
<Icon name="times" onClick={onClose} />
</div>
);
});
@ -267,8 +264,8 @@ const Body = memo<Props>(({ onChange, from, to }) => {
className={styles.body}
tileClassName={styles.title}
value={value}
nextLabel={<span className="fa fa-angle-right" />}
prevLabel={<span className="fa fa-angle-left" />}
nextLabel={<Icon name="angle-right" />}
prevLabel={<Icon name="angle-left" />}
onChange={value => valueToInput(value, onChange)}
locale="en"
/>

@ -2,6 +2,7 @@ import React, { memo } from 'react';
import { css } from 'emotion';
import { GrafanaTheme, TimeOption } from '@grafana/data';
import { useTheme, stylesFactory, selectThemeVariant } from '../../../themes';
import { Icon } from '../../Icon/Icon';
const getStyles = stylesFactory((theme: GrafanaTheme) => {
const background = selectThemeVariant(
@ -48,7 +49,7 @@ export const TimeRangeOption = memo<Props>(({ value, onSelect, selected = false
return (
<div className={styles.container} onClick={() => onSelect(value)} tabIndex={-1}>
<span>{value.display}</span>
{selected ? <i className="fa fa-check" /> : null}
{selected ? <Icon name="check" /> : null}
</div>
);
});

@ -8,8 +8,9 @@ import {
TransformerUIProps,
} from '@grafana/data';
import { ThemeContext } from '../../themes/ThemeContext';
import { css, cx } from 'emotion';
import { css } from 'emotion';
import { InlineList } from '../List/InlineList';
import { Icon } from '../Icon/Icon';
interface FilterByNameTransformerEditorProps extends TransformerUIProps<FilterFieldsByNameTransformerOptions> {}
@ -146,13 +147,11 @@ const FilterPill: React.FC<FilterPillProps> = ({ label, selected, onClick }) =>
onClick={onClick}
>
{selected && (
<i
className={cx(
'fa fa-check',
css`
margin-right: 4px;
`
)}
<Icon
className={css`
margin-right: 4px;
`}
name="check"
/>
)}
{label}

@ -8,8 +8,9 @@ import {
TransformerUIProps,
} from '@grafana/data';
import { ThemeContext } from '../../themes/ThemeContext';
import { css, cx } from 'emotion';
import { css } from 'emotion';
import { InlineList } from '../List/InlineList';
import { Icon } from '../Icon/Icon';
interface FilterByRefIdTransformerEditorProps extends TransformerUIProps<FilterFramesByRefIdTransformerOptions> {}
@ -146,13 +147,11 @@ const FilterPill: React.FC<FilterPillProps> = ({ label, selected, onClick }) =>
onClick={onClick}
>
{selected && (
<i
className={cx(
'fa fa-check',
css`
margin-right: 4px;
`
)}
<Icon
className={css`
margin-right: 4px;
`}
name="check"
/>
)}
{label}

@ -6,6 +6,7 @@ export type IconName =
| 'fa fa-fw fa-unlock'
| 'fa fa-envelope'
| 'fa fa-spinner'
| 'grafana'
| 'question-circle'
| 'angle-up'
| 'history'
@ -14,9 +15,15 @@ export type IconName =
| 'angle-left'
| 'angle-right'
| 'pen'
| 'plane'
| 'envelope'
| 'percentage'
| 'rocket'
| 'power'
| 'trash-alt'
| 'slack'
| 'download-alt'
| 'mobile-android'
| 'slack'
| 'plus-square'
| 'folder-plus'
| 'folder-open'
@ -25,6 +32,7 @@ export type IconName =
| 'import'
| 'exclamation-triangle'
| 'times'
| 'signin'
| 'cloud-upload'
| 'step-backward'
| 'square-shape'
@ -32,14 +40,18 @@ export type IconName =
| 'tag-alt'
| 'forward'
| 'check'
| 'check-circle'
| 'add-panel'
| 'copy'
| 'lock'
| 'panel-add'
| 'arrow-random'
| 'arrow-down'
| 'arrows-h'
| 'comment-alt'
| 'code-branch'
| 'arrow-right'
| 'circle'
| 'arrow-up'
| 'arrow-from-right'
| 'keyboard'
@ -48,7 +60,8 @@ export type IconName =
| 'search-minus'
| 'clock-nine'
| 'sync'
| 'signin'
| 'sign-in-alt'
| 'cllud-download'
| 'cog'
| 'bars'
| 'save'
@ -97,53 +110,70 @@ export type IconName =
| 'signal'
| 'search-plus'
| 'search-minus'
| 'minus-circle'
| 'table'
| 'plus'
| 'heart'
| 'heart-break'
| 'ellipsis-v'
| 'favorite';
export const getAvailableIcons = (): IconName[] => [
'question-circle',
'plane',
'plus',
'plus-circle',
'angle-up',
'shield',
'history',
'angle-down',
'filter',
'angle-left',
'angle-right',
'calendar-alt',
'tag-alt',
'calculator-alt',
'pen',
'repeat',
'external-link-alt',
'envelope',
'percentage',
'rocket',
'power',
'play',
'pause',
'trash-alt',
'slack',
'download-alt',
'mobile-android',
'slack',
'plus-square',
'folder-plus',
'folder-open',
'file-copy-alt',
'exchange-alt',
'import',
'exclamation-triangle',
'times',
'signin',
'cloud-upload',
'step-backward',
'square-shape',
'share-alt',
'camera',
'tag-alt',
'forward',
'check',
'check-circle',
'add-panel',
'copy',
'lock',
'panel-add',
'arrow-random',
'arrow-down',
'arrows-h',
'comment-alt',
'code-branch',
'arrow-right',
'circle',
'arrow-up',
'arrow-from-right',
'arrow-left',
'keyboard',
'search',
'chart-line',
'search-minus',
'clock-nine',
'sync',
'signin',
'sign-in-alt',
'cllud-download',
'cog',
'bars',
'save',
@ -151,12 +181,19 @@ export const getAvailableIcons = (): IconName[] => [
'folder-plus',
'link',
'upload',
'columns',
'home-alt',
'channel-add',
'calendar-alt',
'play',
'pause',
'calculator-alt',
'compass',
'sliders-v-alt',
'bell',
'database',
'user',
'camera',
'plug',
'shield',
'key-skeleton-alt',
@ -164,28 +201,32 @@ export const getAvailableIcons = (): IconName[] => [
'graph-bar',
'book',
'bolt',
'cloud-upload',
'comments-alt',
'list-ul',
'document-info',
'info-circle',
'bug',
'cube',
'history',
'star',
'list-ul',
'edit',
'columns',
'shield',
'eye',
'channel-add',
'eye-slash',
'filter',
'monitor',
'plus-circle',
'arrow-left',
'repeat',
'external-link-alt',
'minus',
'signal',
'search-plus',
'search-minus',
'minus-circle',
'table',
'plus',
'heart',
'heart-break',
'ellipsis-v',
'favorite',
'folder-plus',
'plus-square',
'import',
'folder-open',
'file-copy-alt',
'arrow-down',
'filter',
'arrow-up',
'exchange-alt',
];

@ -26,7 +26,7 @@ export const linkModelToContextMenuItems: (links: LinkModelSupplier<any>) => Con
// TODO: rename to href
url: link.href,
target: link.target,
icon: `fa ${link.target === '_self' ? 'fa-link' : 'fa-external-link'}`,
icon: `${link.target === '_self' ? 'link' : 'external-link-alt'}`,
onClick: link.onClick,
};
});

@ -332,7 +332,7 @@ var (
<div class="diff-group">
<div class="diff-block">
<h2 class="diff-block-title">
<i class="diff-circle diff-circle-{{ getChange .Change }} fa fa-circle"></i>
<icon class="diff-circle diff-circle-{{ getChange .Change }}" name="'circle'" type="'mono'"></icon>
<strong class="diff-title">{{ .Title }}</strong> {{ getChange .Change }}
</h2>
@ -340,7 +340,7 @@ var (
<!-- Overview -->
{{ if .Old }}
<div class="diff-label" ng-non-bindable>{{ .Old }}</div>
<i class="diff-arrow fa fa-long-arrow-right"></i>
<icon name="'arrow-right'"></icon>
{{ end }}
{{ if .New }}
<div class="diff-label" ng-non-bindable>{{ .New }}</div>
@ -381,7 +381,7 @@ var (
<div class="diff-change-item">
{{ if .Old }}
<div class="diff-label" ng-non-bindable>{{ .Old }}</div>
<i class="diff-arrow fa fa-long-arrow-right"></i>
<icon name="'arrow-right'"></icon>
{{ end }}
{{ if .New }}
<div class="diff-label" ng-non-bindable>{{ .New }}</div>
@ -402,7 +402,7 @@ var (
// tplSummary is for basic summaries.
tplSummary = `{{ define "summary" -}}
<div class="diff-group-name">
<i class="diff-circle diff-circle-{{ getChange .Change }} fa fa-circle-o diff-list-circle"></i>
<icon class="diff-circle diff-circle-{{ getChange .Change }} diff-list-circle" name="'circle'"></icon>
{{ if .Count }}
<strong>{{ .Count }}</strong>

@ -5,7 +5,7 @@ import React, { PureComponent } from 'react';
import { InputDatasource, describeDataFrame } from './InputDatasource';
import { InputQuery, InputOptions } from './types';
import { FormLabel, LegacyForms, TableInputCSV } from '@grafana/ui';
import { FormLabel, LegacyForms, TableInputCSV, Icon } from '@grafana/ui';
const { Select } = LegacyForms;
import { DataFrame, toCSV, SelectableValue, MutableDataFrame, QueryEditorProps } from '@grafana/data';
@ -78,7 +78,7 @@ export class InputQueryEditor extends PureComponent<Props, State> {
) : (
<a href={`datasources/edit/${id}/`}>
{name}: {describeDataFrame(datasource.data)} &nbsp;&nbsp;
<i className="fa fa-pencil-square-o" />
<Icon name="pen" />
</a>
)}
</div>

@ -45,7 +45,7 @@ const EmptyListCTA: React.FunctionComponent<Props> = ({
<>
{proTip ? (
<span key="proTipFooter">
<Icon name="plane" />
<Icon name="rocket" />
<> ProTip: {proTip} </>
<a href={proTipLink} target={proTipTarget} className="text-link">
{proTipLinkTitle}

@ -1,5 +1,6 @@
import React, { FC } from 'react';
import config from 'app/core/config';
import { Icon, IconName } from '@grafana/ui';
export interface FooterLink {
text: string;
@ -42,7 +43,7 @@ export let getVersionLinks = (): FooterLink[] => {
if (buildInfo.hasUpdate) {
links.push({
text: `New version available!`,
icon: 'fa fa-download',
icon: 'download-alt',
url: 'https://grafana.com/grafana/download?utm_source=grafana_footer',
target: '_blank',
});
@ -69,7 +70,7 @@ export const Footer: FC = React.memo(() => {
{links.map(link => (
<li key={link.text}>
<a href={link.url} target={link.target} rel="noopener">
<i className={link.icon} /> {link.text}
<Icon name={link.icon as IconName} /> {link.text}
</a>
</li>
))}

@ -9,7 +9,7 @@ describe('PageHeader', () => {
beforeAll(() => {
const nav = {
main: {
icon: 'fa fa-folder-open',
icon: 'folder-open',
id: 'node',
subTitle: 'node subtitle',
url: '',
@ -30,7 +30,7 @@ describe('PageHeader', () => {
beforeAll(() => {
const nav = {
main: {
icon: 'fa fa-folder-open',
icon: 'folder-open',
id: 'child',
subTitle: 'child subtitle',
url: '',

@ -89,11 +89,11 @@ export default class PermissionsListItem extends PureComponent<Props> {
<td>
{!item.inherited ? (
<a className="btn btn-danger btn-small" onClick={this.onRemoveItem}>
<Icon name="times" />
<Icon name="times" style={{ marginBottom: 0 }} />
</a>
) : (
<button className="btn btn-inverse btn-small">
<Icon name="lock" />
<Icon name="lock" style={{ marginBottom: '3px' }} />
</button>
)}
</td>

@ -83,9 +83,27 @@ exports[`TeamPicker renders correctly 1`] = `
<div
className="gf-form-select-box__indicators css-q46mcr-IndicatorsContainer"
>
<span
className="gf-form-select-box__select-arrow "
/>
<div
className="css-1cvxpvr"
>
<svg
className="css-sr6nr"
fill="currentColor"
height={16}
style={
Object {
"marginTop": "7px",
}
}
viewBox="0 0 24 24"
width={16}
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M17,9.17a1,1,0,0,0-1.41,0L12,12.71,8.46,9.17a1,1,0,0,0-1.41,0,1,1,0,0,0,0,1.42l4.24,4.24a1,1,0,0,0,1.42,0L17,10.59A1,1,0,0,0,17,9.17Z"
/>
</svg>
</div>
</div>
</div>
</div>

@ -83,9 +83,27 @@ exports[`UserPicker renders correctly 1`] = `
<div
className="gf-form-select-box__indicators css-q46mcr-IndicatorsContainer"
>
<span
className="gf-form-select-box__select-arrow "
/>
<div
className="css-1cvxpvr"
>
<svg
className="css-sr6nr"
fill="currentColor"
height={16}
style={
Object {
"marginTop": "7px",
}
}
viewBox="0 0 24 24"
width={16}
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M17,9.17a1,1,0,0,0-1.41,0L12,12.71,8.46,9.17a1,1,0,0,0-1.41,0,1,1,0,0,0,0,1.42l4.24,4.24a1,1,0,0,0,1.42,0L17,10.59A1,1,0,0,0,17,9.17Z"
/>
</svg>
</div>
</div>
</div>
</div>

@ -34,11 +34,11 @@ export class HelpModal extends React.PureComponent {
'Time Range': [
{ keys: ['t', 'z'], description: 'Zoom out time range' },
{
keys: ['t', <i className="fa fa-long-arrow-left" />],
keys: ['t', <Icon name="arrow-left" />],
description: 'Move time range back',
},
{
keys: ['t', <i className="fa fa-long-arrow-right" />],
keys: ['t', <Icon name="arrow-right" />],
description: 'Move time range forward',
},
],

@ -15,7 +15,7 @@
spellcheck="false"
ng-change="ctrl.onQueryChange()"
/>
<icon class="gf-form-input-icon" name="'search'"></icon>
<icon class="gf-form-input-icon" name="'search'" style="margin-top: -5px"></icon>
</label>
<div class="page-action-bar__spacer"></div>
<a

@ -204,7 +204,7 @@ export class ManageDashboardsCtrl {
title: 'Delete',
text: text,
text2: text2,
icon: 'fa-trash',
icon: 'trash-alt',
yesText: 'Delete',
onConfirm: () => {
this.deleteFoldersAndDashboards(data.folderUids, data.dashboardUids);

@ -14,7 +14,7 @@
>
</gf-form-checkbox>
</div>
<i class="search-section__header__icon" ng-class="section.icon"></i>
<icon class="search-section__header__icon" ng-class="section.icon"></icon>
<span class="search-section__header__text">{{::section.title}}</span>
<a ng-show="section.url" href="{{section.url}}" class="search-section__header__link">
<icon name="'cog'"></icon>

@ -1,6 +1,7 @@
import React, { FC } from 'react';
import { connectWithStore } from 'app/core/utils/connectWithReduxStore';
import { StoreState } from 'app/types';
import { Icon } from '@grafana/ui';
export const SignIn: FC<any> = ({ url }) => {
const loginUrl = `login?redirect=${encodeURIComponent(url)}`;
@ -8,7 +9,7 @@ export const SignIn: FC<any> = ({ url }) => {
<div className="sidemenu-item">
<a href={loginUrl} className="sidemenu-link" target="_self">
<span className="icon-circle sidemenu-icon">
<i className="fa fa-fw fa-sign-in" />
<Icon name="sign-in-alt" />
</span>
</a>
<a href={loginUrl} target="_self">

@ -12,8 +12,8 @@ exports[`Render should render component 1`] = `
<span
className="icon-circle sidemenu-icon"
>
<i
className="fa fa-fw fa-sign-in"
<Icon
name="sign-in-alt"
/>
</span>
</a>

@ -5,7 +5,7 @@ const defaultSuccessNotification = {
title: '',
text: '',
severity: AppNotificationSeverity.Success,
icon: 'fa fa-check',
icon: 'check',
timeout: AppNotificationTimeout.Success,
};
@ -13,7 +13,7 @@ const defaultWarningNotification = {
title: '',
text: '',
severity: AppNotificationSeverity.Warning,
icon: 'fa fa-exclamation',
icon: 'exclamation-triangle',
timeout: AppNotificationTimeout.Warning,
};
@ -21,7 +21,7 @@ const defaultErrorNotification = {
title: '',
text: '',
severity: AppNotificationSeverity.Error,
icon: 'fa fa-exclamation-triangle',
icon: 'exclamation-triangle',
timeout: AppNotificationTimeout.Error,
};

@ -61,7 +61,7 @@ export function getWarningNav(text: string, subTitle?: string): NavModel {
const node = {
text,
subTitle,
icon: 'fa fa-fw fa-warning',
icon: 'exclamation-triangle',
};
return {
breadcrumbs: [node],

@ -4,7 +4,7 @@ function getNotFoundModel(): NavModel {
const node: NavModelItem = {
id: 'not-found',
text: 'Page not found',
icon: 'fa fa-fw fa-warning',
icon: 'exclamation-triangle',
subTitle: '404 Error',
url: 'not-found',
};

@ -26,7 +26,7 @@ export class SearchSrv {
if (result.length > 0) {
sections['recent'] = {
title: 'Recent',
icon: 'clock-o',
icon: 'clock-nine',
score: -1,
removable: true,
expanded: this.recentIsOpen,
@ -82,7 +82,7 @@ export class SearchSrv {
if (result.length > 0) {
sections['starred'] = {
title: 'Starred',
icon: 'star-o',
icon: 'star',
score: -2,
expanded: this.starredIsOpen,
toggle: this.toggleStarred.bind(this),

@ -99,7 +99,7 @@ export class UtilSrv {
scope.onConfirm = payload.onConfirm;
scope.onAltAction = payload.onAltAction;
scope.altActionText = payload.altActionText;
scope.icon = payload.icon || 'fa-check';
scope.icon = payload.icon || 'check';
scope.yesText = payload.yesText || 'Yes';
scope.noText = payload.noText || 'Cancel';
scope.confirmTextValid = scope.confirmText ? false : true;

@ -43,7 +43,7 @@ describe('ManageDashboards', () => {
id: 399,
title: 'Dashboard Test',
url: 'dashboard/db/dashboard-test',
icon: 'fa fa-folder',
icon: 'folder',
tags,
isStarred: false,
},
@ -54,7 +54,7 @@ describe('ManageDashboards', () => {
{
id: 0,
title: 'General',
icon: 'fa fa-folder-open',
icon: 'folder-open',
uri: 'db/something-else',
type: 'dash-db',
items: [
@ -62,7 +62,7 @@ describe('ManageDashboards', () => {
id: 500,
title: 'Dashboard Test',
url: 'dashboard/db/dashboard-test',
icon: 'fa fa-folder',
icon: 'folder',
tags,
isStarred: false,
},
@ -98,7 +98,7 @@ describe('ManageDashboards', () => {
id: 399,
title: 'Dashboard Test',
url: 'dashboard/db/dashboard-test',
icon: 'fa fa-folder',
icon: 'folder',
tags,
isStarred: false,
},
@ -130,7 +130,7 @@ describe('ManageDashboards', () => {
id: 399,
title: 'Dashboard Test',
url: 'dashboard/db/dashboard-test',
icon: 'fa fa-folder',
icon: 'folder',
tags,
isStarred: false,
folderId: 410,
@ -142,7 +142,7 @@ describe('ManageDashboards', () => {
id: 500,
title: 'Dashboard Test',
url: 'dashboard/db/dashboard-test',
icon: 'fa fa-folder',
icon: 'folder',
tags,
folderId: 499,
isStarred: false,

@ -188,7 +188,7 @@ export default class AdminEditUserCtrl {
$scope.appEvent(CoreEvents.showConfirmModal, {
title: 'Delete',
text: 'Do you want to delete ' + user.login + '?',
icon: 'fa-trash',
icon: 'trash-alt',
yesText: 'Delete',
onConfirm: () => {
promiseToDigest($scope)(

@ -21,7 +21,7 @@ export default class AdminListOrgsCtrl {
title: 'Delete',
text: `Do you want to delete organization ${org.name}?`,
text2: 'All dashboards for this organization will be removed!',
icon: 'fa-trash',
icon: 'trash-alt',
yesText: 'Delete',
onConfirm: async () => {
await getBackendSrv().delete('/api/orgs/' + org.id);

@ -1,6 +1,7 @@
import React, { PureComponent } from 'react';
import { dateTime } from '@grafana/data';
import { LdapUserSyncInfo } from 'app/types';
import { Icon } from '@grafana/ui';
interface Props {
disableSync: boolean;
@ -43,7 +44,7 @@ export class UserSyncInfo extends PureComponent<Props, State> {
<>
<button className={`btn btn-secondary pull-right`} onClick={this.onSyncClick} disabled={isDisabled}>
<span className="btn-title">Sync user</span>
{isSyncing && <i className="fa fa-spinner fa-fw fa-spin run-icon" />}
{isSyncing && <Icon name="fa fa-spinner" className="fa-fw fa-spin run-icon" />}
</button>
<div className="clearfix" />

@ -1,5 +1,5 @@
import React, { FC } from 'react';
import { Alert } from '@grafana/ui';
import { Alert, Icon } from '@grafana/ui';
import { AppNotificationSeverity, LdapConnectionInfo, LdapServerInfo } from 'app/types';
interface Props {
@ -27,9 +27,9 @@ export const LdapConnectionStatus: FC<Props> = ({ ldapConnectionInfo }) => {
<td>{serverInfo.port}</td>
<td>
{serverInfo.available ? (
<i className="fa fa-fw fa-check pull-right" />
<Icon name="check" className="pull-right" />
) : (
<i className="fa fa-fw fa-exclamation-triangle pull-right" />
<Icon name="exclamation-triangle" className="pull-right" />
)}
</td>
</tr>

@ -1,5 +1,6 @@
import React, { PureComponent } from 'react';
import { dateTime } from '@grafana/data';
import { Icon } from '@grafana/ui';
import { SyncInfo } from 'app/types';
interface Props {
@ -35,7 +36,7 @@ export class LdapSyncInfo extends PureComponent<Props, State> {
LDAP Synchronisation
<button className={`btn btn-secondary pull-right`} onClick={this.handleSyncClick} hidden={true}>
<span className="btn-title">Bulk-sync now</span>
{isSyncing && <i className="fa fa-spinner fa-fw fa-spin run-icon" />}
{isSyncing && <Icon name="fa fa-spinner" className="fa-fw fa-spin run-icon" />}
</button>
</h3>
<div className="gf-form-group">

@ -1,5 +1,5 @@
import React, { FC } from 'react';
import { Tooltip } from '@grafana/ui';
import { Tooltip, Icon } from '@grafana/ui';
import { LdapRole } from 'app/types';
interface Props {
@ -21,7 +21,7 @@ export const LdapUserGroups: FC<Props> = ({ groups, showAttributeMapping }) => {
Organization
<Tooltip placement="top" content="Only the first match for an Organization will be used" theme={'info'}>
<span className="gf-form-help-icon">
<i className="fa fa-info-circle" />
<Icon name="info-circle" />
</span>
</Tooltip>
</th>
@ -43,7 +43,7 @@ export const LdapUserGroups: FC<Props> = ({ groups, showAttributeMapping }) => {
No match
<Tooltip placement="top" content="No matching groups found" theme={'info'}>
<span className="gf-form-help-icon">
<i className="fa fa-info-circle" />
<Icon name="info-circle" />
</span>
</Tooltip>
</span>

@ -34,11 +34,11 @@ export const LdapUserPermissions: FC<Props> = ({ permissions }) => {
<td>
{permissions.isDisabled ? (
<>
<i className="fa fa-fw fa-times" /> Inactive
<Icon name="times" /> Inactive
</>
) : (
<>
<i className="fa fa-fw fa-check" /> Active
<Icon name="check" /> Active
</>
)}
</td>

@ -1,5 +1,5 @@
import React, { FC } from 'react';
import { Tooltip } from '@grafana/ui';
import { Tooltip, Icon } from '@grafana/ui';
import { LdapTeam } from 'app/types';
interface Props {
@ -36,7 +36,7 @@ export const LdapUserTeams: FC<Props> = ({ teams, showAttributeMapping }) => {
No match
<Tooltip placement="top" content="No matching teams found" theme={'info'}>
<span className="gf-form-help-icon">
<i className="fa fa-info-circle" />
<Icon name="info-circle" />
</span>
</Tooltip>
</div>

@ -42,7 +42,7 @@
</td>
<td style="width: 1%">
<a ng-click="removeOrgUser(orgUser)" class="btn btn-danger btn-small">
<icon name="'times'"></icon>
<icon name="'times'" style="margin-bottom: 0;"></icon>
</a>
</td>
</tr>

@ -108,7 +108,7 @@
</td>
<td style="width: 1%">
<a ng-click="removeOrgUser(org)" class="btn btn-danger btn-small">
<icon name="'times'"></icon>
<icon name="'times'" style="margin-bottom: 0;"></icon>
</a>
</td>
</tr>

@ -30,7 +30,7 @@
</td>
<td class="text-right">
<a ng-click="deleteOrg(org)" class="btn btn-danger btn-small">
<icon name="'times'" size="sm"></icon>
<icon name="'times'" size="sm" style="margin-bottom: 0;"></icon>
</a>
</td>
</tr>

@ -108,27 +108,27 @@ export class AlertTabCtrl {
getNotificationIcon(type: string): string {
switch (type) {
case 'email':
return 'fa fa-envelope';
return 'envelope';
case 'slack':
return 'fa fa-slack';
return 'slack';
case 'victorops':
return 'fa fa-pagelines';
case 'webhook':
return 'fa fa-cubes';
return 'cube';
case 'pagerduty':
return 'fa fa-bullhorn';
case 'opsgenie':
return 'fa fa-bell';
return 'bell';
case 'hipchat':
return 'fa fa-mail-forward';
case 'pushover':
return 'fa fa-mobile';
return 'mobile-android';
case 'kafka':
return 'fa fa-random';
return 'arrow-random';
case 'teams':
return 'fa fa-windows';
}
return 'fa fa-bell';
return 'bell';
}
getNotifications() {
@ -412,7 +412,7 @@ export class AlertTabCtrl {
title: 'Delete Alert',
text: 'Are you sure you want to delete this alert rule?',
text2: 'You need to save dashboard for the delete to take effect',
icon: 'fa-trash',
icon: 'trash-alt',
yesText: 'Delete',
onConfirm: () => {
delete this.panel.alert;
@ -461,7 +461,7 @@ export class AlertTabCtrl {
appEvents.emit(CoreEvents.showConfirmModal, {
title: 'Delete Alert History',
text: 'Are you sure you want to remove all history & annotations for this alert?',
icon: 'fa-trash',
icon: 'trash-alt',
yesText: 'Yes',
onConfirm: () => {
promiseToDigest(this.$scope)(

@ -1,5 +1,6 @@
import React, { PureComponent } from 'react';
import { getBackendSrv } from '@grafana/runtime';
import { Icon } from '@grafana/ui';
import alertDef from './state/alertDef';
import { DashboardModel } from '../dashboard/state/DashboardModel';
@ -51,7 +52,7 @@ class StateHistory extends PureComponent<Props, State> {
appEvents.emit(CoreEvents.showConfirmModal, {
title: 'Delete Alert History',
text: 'Are you sure you want to remove all history & annotations for this alert?',
icon: 'fa-trash',
icon: 'trash-alt',
yesText: 'Yes',
onConfirm: () => {
getBackendSrv()
@ -78,7 +79,7 @@ class StateHistory extends PureComponent<Props, State> {
<div className="p-b-1">
<span className="muted">Last 50 state changes</span>
<button className="btn btn-small btn-danger pull-right" onClick={this.clearHistory}>
<i className="fa fa-trash" /> {` Clear history`}
<Icon name="trash-alt" style={{ marginRight: '4px' }} size="xs" /> {` Clear history`}
</button>
</div>
)}
@ -88,7 +89,7 @@ class StateHistory extends PureComponent<Props, State> {
return (
<li className="alert-rule-item" key={`${item.time}-${index}`}>
<div className={`alert-rule-item__icon ${item.stateModel.stateClass}`}>
<i className={item.stateModel.iconClass} />
<Icon name={item.stateModel.iconClass} size="xl" />
</div>
<div className="alert-rule-item__body">
<div className="alert-rule-item__header">

@ -1,5 +1,5 @@
import React, { PureComponent } from 'react';
import { LoadingPlaceholder, JSONFormatter } from '@grafana/ui';
import { LoadingPlaceholder, JSONFormatter, Icon } from '@grafana/ui';
import appEvents from 'app/core/app_events';
import { CopyToClipboard } from 'app/core/components/CopyToClipboard/CopyToClipboard';
@ -83,12 +83,12 @@ export class TestRuleResult extends PureComponent<Props, State> {
const collapse = (
<>
<i className="fa fa-minus-square-o" /> Collapse All
<Icon name="minus-circle" /> Collapse All
</>
);
const expand = (
<>
<i className="fa fa-plus-square-o" /> Expand All
<Icon name="plus-circle" /> Expand All
</>
);
return allNodesExpanded ? collapse : expand;
@ -114,7 +114,7 @@ export class TestRuleResult extends PureComponent<Props, State> {
text={this.getTextForClipboard}
onSuccess={this.onClipboardSuccess}
>
<i className="fa fa-clipboard" /> Copy to Clipboard
<Icon name="copy" /> Copy to Clipboard
</CopyToClipboard>
</div>

@ -1,7 +1,7 @@
<div class="modal-body">
<div class="modal-header">
<h2 class="modal-header-title">
<i class="fa fa-info-circle"></i>
<icon name="'info-circle'"></icon>
<span class="p-l-1">Adding an Alert</span>
</h2>

@ -1,5 +1,7 @@
<div ng-if="ctrl.panel.alert">
<div class="alert alert-error m-b-2" ng-show="ctrl.error"><i class="fa fa-warning"></i> {{ctrl.error}}</div>
<div class="alert alert-error m-b-2" ng-show="ctrl.error">
<icon name="'exclamation-triangle'"></icon> {{ctrl.error}}
</div>
<div class="panel-options-group">
<div class="panel-options-group__body">
<div class="gf-form-group">
@ -35,7 +37,9 @@
</div>
</div>
<div class="gf-form" ng-if="ctrl.frequencyWarning">
<label class="gf-form-label text-warning"> <i class="fa fa-warning"></i> {{ctrl.frequencyWarning}} </label>
<label class="gf-form-label text-warning">
<icon name="'exclamation-triangle'"></icon> {{ctrl.frequencyWarning}}
</label>
</div>
</div>
@ -98,7 +102,7 @@
<div class="gf-form">
<label class="gf-form-label">
<a class="pointer" tabindex="1" ng-click="ctrl.removeCondition($index)">
<i class="fa fa-trash"></i>
<icon name="'trash-alt'"></icon>
</a>
</label>
</div>
@ -107,7 +111,7 @@
<div class="gf-form">
<label class="gf-form-label dropdown">
<a class="pointer dropdown-toggle" data-toggle="dropdown">
<i class="fa fa-plus"></i>
<icon name="'plus-circle'"></icon>
</a>
<ul class="dropdown-menu" role="menu">
<li ng-repeat="ct in ctrl.conditionTypes" role="menuitem">
@ -166,7 +170,7 @@
</div>
<div class="gf-form" ng-repeat="nc in ctrl.alertNotifications">
<span class="gf-form-label">
<i class="{{nc.iconClass}}"></i>
<icon name="'{{nc.iconClass}}'"></icon>
&nbsp;{{nc.name}}&nbsp;<span ng-if="nc.isDefault">(default)</span>
<icon
name="'times'"
@ -206,7 +210,7 @@
/>
<label class="gf-form-label">
<a class="pointer" tabindex="1" ng-click="ctrl.removeAlertRuleTag(name)">
<i class="fa fa-trash"></i>
<icon name="'trash-alt'"></icon>
</a>
</label>
</div>
@ -230,7 +234,7 @@
<div class="gf-form">
<label class="gf-form-label">
<a class="pointer" tabindex="1" ng-click="ctrl.addAlertRuleTag()">
<i class="fa fa-plus"></i>&nbsp;Add Tag
<icon name="'plus-circle'"></icon>&nbsp;Add Tag
</a>
</label>
</div>

@ -35,7 +35,7 @@
default
</span>
<a ng-click="ctrl.deleteNotification(notification.id)" class="btn btn-danger btn-small">
<icon name="'times'"></icon>
<icon name="'times'" style="margin-top: 2px"></icon>
</a>
</td>
</tr>

@ -82,7 +82,7 @@ function getStateDisplayModel(state: string) {
case 'alerting': {
return {
text: 'ALERTING',
iconClass: 'heartbeat',
iconClass: 'heart-break',
stateClass: 'alert-state-critical',
};
}

@ -131,7 +131,7 @@ describe('Alert rules', () => {
state: 'alerting',
stateAge: newStateDateAge,
stateClass: 'alert-state-critical',
stateIcon: 'heartbeat',
stateIcon: 'heart-break',
stateText: 'ALERTING',
url: '/d/ggHbN42mk/alerting-with-testdata',
},

@ -27,7 +27,7 @@ export class AnnotationsEditorCtrl {
emptyListCta = {
title: 'There are no custom annotation queries added yet',
buttonIcon: 'gicon gicon-annotation',
buttonIcon: 'comment-alt',
buttonTitle: 'Add Annotation Query',
infoBox: {
__html: `<p>Annotations provide a way to integrate event data into your graphs. They are visualized as vertical lines

@ -2,8 +2,8 @@
<div class="page-action-bar">
<h3 class="dashboard-settings__header">
<a ng-click="ctrl.backToList()">Annotations</a>
<span ng-show="ctrl.mode === 'new'"><i class="fa fa-fw fa-chevron-right"></i> New</span>
<span ng-show="ctrl.mode === 'edit'"><i class="fa fa-fw fa-chevron-right"></i> Edit</span>
<span ng-show="ctrl.mode === 'new'"><icon name="'angle-right'"></icon> New</span>
<span ng-show="ctrl.mode === 'edit'"><icon name="'angle-right'"></icon> Edit</span>
</h3>
<div class="page-action-bar__spacer"></div>
@ -31,20 +31,20 @@
<tbody>
<tr ng-repeat="annotation in ctrl.annotations track by annotation.name">
<td style="width:90%" ng-hide="annotation.builtIn" class="pointer" ng-click="ctrl.edit(annotation)">
<i class="fa fa-comment" style="color:{{ annotation.iconColor }}"></i> &nbsp; {{ annotation.name }}
<icon name="'comment-alt'" style="color:{{ annotation.iconColor }}"></icon> &nbsp; {{ annotation.name }}
</td>
<td style="width:90%" ng-show="annotation.builtIn" class="pointer" ng-click="ctrl.edit(annotation)">
<i class="gicon gicon-annotation"></i> &nbsp;
<icon name="'comment-alt'"></icon> &nbsp;
<em class="muted">{{ annotation.name }} (Built-in)</em>
</td>
<td class="pointer" ng-click="ctrl.edit(annotation)">
{{ annotation.datasource || 'Default' }}
</td>
<td style="width: 1%">
<i ng-click="ctrl.move($index,-1)" ng-hide="$first" class="pointer fa fa-arrow-up"></i>
<icon ng-click="ctrl.move($index,-1)" ng-hide="$first" name="'arrow-up'"></icon>
</td>
<td style="width: 1%">
<i ng-click="ctrl.move($index,1)" ng-hide="$last" class="pointer fa fa-arrow-down"></i>
<icon ng-click="ctrl.move($index,1)" ng-hide="$last" name="'arrow-down'"></icon>
</td>
<td style="width: 1%">
<a
@ -52,7 +52,7 @@
class="btn btn-danger btn-small"
ng-hide="annotation.builtIn"
>
<icon name="'times'"></icon>
<icon name="'times'" style="margin-bottom: 0;"></icon>
</a>
</td>
</tr>

@ -11,7 +11,7 @@ export const ApiKeysAddedModal = (props: Props) => {
<div className="modal-body">
<div className="modal-header">
<h2 className="modal-header-title">
<Icon name="key-skeleton-alt" />
<Icon name="key-skeleton-alt" size="lg" />
<span className="p-l-1">API Key Created</span>
</h2>

@ -12,6 +12,7 @@ exports[`Render should render component 1`] = `
>
<Icon
name="key-skeleton-alt"
size="lg"
/>
<span
className="p-l-1"

@ -113,7 +113,7 @@ export class DashLinksContainerCtrl {
keepTime: linkDef.keepTime,
includeVars: linkDef.includeVars,
target: linkDef.targetBlank ? '_blank' : '_self',
icon: 'fa fa-bars',
icon: 'bars',
asDropdown: true,
},
]);
@ -160,7 +160,7 @@ export class DashLinksContainerCtrl {
title: dash.title,
url: dash.url,
target: link.target === '_self' ? '' : link.target,
icon: 'fa fa-th-large',
icon: 'table',
keepTime: link.keepTime,
includeVars: link.includeVars,
});

@ -22,7 +22,7 @@ export class DashLinksEditorCtrl {
emptyListCta = {
title: 'There are no dashboard links added yet',
buttonIcon: 'gicon gicon-link',
buttonIcon: 'link',
buttonTitle: 'Add Dashboard Link',
infoBox: {
__html: `<p>

@ -1,8 +1,8 @@
<div class="page-action-bar">
<h3 class="dashboard-settings__header">
<a ng-click="ctrl.backToList()">Dashboard Links</a>
<span ng-show="ctrl.mode === 'new'"><i class="fa fa-fw fa-chevron-right"></i> New</span>
<span ng-show="ctrl.mode === 'edit'"><i class="fa fa-fw fa-chevron-right"></i> Edit</span>
<span ng-show="ctrl.mode === 'new'"><icon name="'angle-right'"></icon> New</span>
<span ng-show="ctrl.mode === 'edit'"><icon name="'angle-right'"></icon> Edit</span>
</h3>
<div class="page-action-bar__spacer"></div>
@ -41,7 +41,7 @@
<tbody>
<tr ng-repeat="link in ctrl.dashboard.links">
<td class="pointer" ng-click="ctrl.editLink(link)">
<i class="fa fa-fw fa-external-link"></i>
<icon name="'external-link-alt'"></icon>
{{ link.type }}
</td>
<td>
@ -62,14 +62,14 @@
</span>
</td>
<td style="width: 1%">
<i ng-click="ctrl.moveLink($index, -1)" ng-hide="$first" class="pointer fa fa-arrow-up"></i>
<icon ng-click="ctrl.moveLink($index, -1)" ng-hide="$first" name="'arrow-up'"></icon>
</td>
<td style="width: 1%">
<i ng-click="ctrl.moveLink($index, 1)" ng-hide="$last" class="pointer fa fa-arrow-down"></i>
<icon ng-click="ctrl.moveLink($index, 1)" ng-hide="$last" name="'arrow-down'"></icon>
</td>
<td style="width: 1%">
<a ng-click="ctrl.deleteLink($index)" class="btn btn-danger btn-small" ng-hide="annotation.builtIn">
<icon name="'times'"></icon>
<icon name="'times'" style="margin-bottom: 0;"></icon>
</a>
</td>
</tr>

@ -102,11 +102,12 @@ class DashNav extends PureComponent<Props> {
const { dashboard, isFullscreen } = this.props;
/* Hard-coded value so we don't have to wrap whole component in withTheme because of 1 variable */
const iconClassName = css`
margin-right: 8px;
margin-right: 4px;
margin-bottom: -1px;
`;
const mainIconClassName = css`
margin-right: 8px;
margin-right: 4px;
margin-bottom: 3px;
`;
const folderTitle = dashboard.meta.folderTitle;
@ -116,7 +117,7 @@ class DashNav extends PureComponent<Props> {
<>
<div>
<div className="navbar-page-btn">
{!isFullscreen && <Icon name="apps" size="xl" className={mainIconClassName} />}
{!isFullscreen && <Icon name="apps" size="lg" className={mainIconClassName} />}
{haveFolder && (
<>
<a className="navbar-page-btn__folder" onClick={this.onFolderNameClick}>

@ -1,5 +1,6 @@
import React from 'react';
import classNames from 'classnames';
import { Icon } from '@grafana/ui';
import { PanelModel } from '../../state/PanelModel';
import { DashboardModel } from '../../state/DashboardModel';
import templateSrv from 'app/features/templating/template_srv';
@ -74,11 +75,6 @@ export class DashboardRow extends React.Component<DashboardRowProps, any> {
'dashboard-row': true,
'dashboard-row--collapsed': this.state.collapsed,
});
const chevronClass = classNames({
fa: true,
'fa-chevron-down': !this.state.collapsed,
'fa-chevron-right': this.state.collapsed,
});
const title = templateSrv.replaceWithText(this.props.panel.title, this.props.panel.scopedVars);
const count = this.props.panel.panels ? this.props.panel.panels.length : 0;
@ -88,7 +84,7 @@ export class DashboardRow extends React.Component<DashboardRowProps, any> {
return (
<div className={classes}>
<a className="dashboard-row__title pointer" onClick={this.onToggle}>
<i className={chevronClass} />
<Icon name={this.state.collapsed ? 'angle-right' : 'angle-down'} />
{title}
<span className="dashboard-row__panel_count">
({count} {panels})
@ -97,10 +93,10 @@ export class DashboardRow extends React.Component<DashboardRowProps, any> {
{canEdit && (
<div className="dashboard-row__actions">
<a className="pointer" onClick={this.onOpenSettings}>
<i className="gicon gicon-cog" />
<Icon name="cog" />
</a>
<a className="pointer" onClick={this.onDelete}>
<i className="fa fa-trash" />
<Icon name="trash-alt" />
</a>
</div>
)}

@ -71,22 +71,22 @@ export class SettingsCtrl {
this.sections.push({
title: 'General',
id: 'settings',
icon: 'gicon gicon-preferences',
icon: 'sliders-v-alt',
});
this.sections.push({
title: 'Annotations',
id: 'annotations',
icon: 'gicon gicon-annotation',
icon: 'comment-alt',
});
this.sections.push({
title: 'Variables',
id: 'templating',
icon: 'gicon gicon-variable',
icon: 'calculator-alt',
});
this.sections.push({
title: 'Links',
id: 'links',
icon: 'gicon gicon-link',
icon: 'link',
});
}
@ -94,7 +94,7 @@ export class SettingsCtrl {
this.sections.push({
title: 'Versions',
id: 'versions',
icon: 'fa fa-fw fa-history',
icon: 'history',
});
}
@ -102,14 +102,14 @@ export class SettingsCtrl {
this.sections.push({
title: 'Permissions',
id: 'permissions',
icon: 'fa fa-fw fa-lock',
icon: 'lock',
});
}
if (this.dashboard.meta.canMakeEditable) {
this.sections.push({
title: 'General',
icon: 'gicon gicon-preferences',
icon: 'sliders-v-alt',
id: 'make_editable',
});
}
@ -117,7 +117,7 @@ export class SettingsCtrl {
this.sections.push({
title: 'JSON Model',
id: 'dashboard_json',
icon: 'gicon gicon-json',
icon: 'arrow',
});
const params = this.$location.search();
@ -145,7 +145,7 @@ export class SettingsCtrl {
this.sections.unshift({
title: 'Not found',
id: '404',
icon: 'fa fa-fw fa-warning',
icon: 'exclamation-triangle',
});
this.viewId = '404';
}
@ -201,7 +201,7 @@ export class SettingsCtrl {
File path: ${this.dashboard.meta.provisionedExternalId}
`,
text2htmlBind: true,
icon: 'fa-trash',
icon: 'trash-alt',
noText: 'OK',
});
return;
@ -220,7 +220,7 @@ export class SettingsCtrl {
title: 'Delete',
text: 'Do you want to delete this dashboard?',
text2: text2,
icon: 'fa-trash',
icon: 'trash-alt',
confirmText: confirmText,
yesText: 'Delete',
onConfirm: () => {

@ -4,7 +4,7 @@
ng-class="{active: ctrl.viewId === section.id}"
ng-repeat="section in ctrl.sections"
aria-label="{{ctrl.selectors.sectionItems(section.title)}}">
<i class="{{::section.icon}}"></i>
<icon name="'{{::section.icon}}'" style="margin-right: 4px;"></icon>
{{::section.title}}
</a>

@ -1,7 +1,7 @@
<div class="modal-body">
<div class="modal-header">
<h2 class="modal-header-title">
<i class="fa fa-copy"></i>
<icon name="'copy'" size="'lg'"></icon>
<span class="p-l-1">Row Options</span>
</h2>

@ -130,7 +130,7 @@ export class ShareLink extends PureComponent<Props, State> {
{panel && (
<div className="gf-form">
<a href={imageUrl} target="_blank" aria-label={selectors.linkToRenderedImage}>
<i className="fa fa-camera"></i> Direct link rendered image
<Icon name="camera" /> Direct link rendered image
</a>
</div>
)}

@ -266,7 +266,7 @@ export class ShareSnapshot extends PureComponent<Props, State> {
<div className="gf-form" style={{ marginTop: '40px' }}>
<div className="gf-form-row">
<a href={snapshotUrl} className="large share-modal-link" target="_blank">
<i className="fa fa-external-link-square"></i> {snapshotUrl}
<Icon name="external-link-alt" /> {snapshotUrl}
</a>
<br />
<ClipboardButton variant="secondary" getText={this.getSnapshotUrl} onClipboardCopy={this.onSnapshotUrlCopy}>
@ -304,7 +304,7 @@ export class ShareSnapshot extends PureComponent<Props, State> {
<div className="share-modal-header">
{isLoading ? (
<div className="share-modal-big-icon">
<i className="fa fa-spinner fa-spin"></i>
<Icon name="fa fa-spinner" className="fa-spin" />
</div>
) : (
<Icon name="camera" className="share-modal-big-icon" size="xxl" />

@ -4,7 +4,7 @@ const template = `
<div class="modal-body">
<div class="modal-header">
<h2 class="modal-header-title">
<i class="fa fa-exclamation"></i>
<icon name="'exclamation-triangle'" size="'lg'"></icon>
<span class="p-l-1">Unsaved changes</span>
</h2>

@ -1,8 +1,8 @@
<h3 class="dashboard-settings__header">
<a ng-click="ctrl.switchMode('list')">Versions</a>
<span ng-show="ctrl.mode === 'compare'">
<i class="fa fa-fw fa-chevron-right"></i> Comparing {{ctrl.baseInfo.version}}
<i class="fa fa-arrows-h"></i>
<icon name="'angle-right'"></icon> Comparing {{ctrl.baseInfo.version}}
<icon name="'arrows-h'"></icon>
{{ctrl.newInfo.version}}
<cite class="muted" ng-if="ctrl.isNewLatest">(Latest)</cite>
</span>
@ -10,7 +10,7 @@
<div ng-if="ctrl.mode === 'list'">
<div ng-if="ctrl.loading">
<i class="fa fa-spinner fa-spin"></i>
<icon name="'fa fa-spinner'" class="fa-spin"></icon>
<em>Fetching history list&hellip;</em>
</div>
@ -29,8 +29,17 @@
</thead>
<tbody>
<tr ng-repeat="revision in ctrl.revisions">
<td class="filter-table__switch-cell" bs-tooltip="!revision.checked && ctrl.canCompare ? 'You can only compare 2 versions at a time' : ''" data-placement="right">
<gf-form-checkbox switch-class="gf-form-switch--table-cell" checked="revision.checked" on-change="ctrl.revisionSelectionChanged()" ng-disabled="!revision.checked && ctrl.canCompare">
<td
class="filter-table__switch-cell"
bs-tooltip="!revision.checked && ctrl.canCompare ? 'You can only compare 2 versions at a time' : ''"
data-placement="right"
>
<gf-form-checkbox
switch-class="gf-form-switch--table-cell"
checked="revision.checked"
on-change="ctrl.revisionSelectionChanged()"
ng-disabled="!revision.checked && ctrl.canCompare"
>
</gf-form-checkbox>
</td>
<td class="text-center">{{revision.version}}</td>
@ -38,11 +47,15 @@
<td>{{revision.createdBy}}</td>
<td>{{revision.message}}</td>
<td class="text-right">
<a class="btn btn-inverse btn-small" ng-show="revision.version !== ctrl.dashboard.version" ng-click="ctrl.restore(revision.version)">
<i class="fa fa-history"></i>&nbsp;&nbsp;Restore
<a
class="btn btn-inverse btn-small"
ng-show="revision.version !== ctrl.dashboard.version"
ng-click="ctrl.restore(revision.version)"
>
<icon name="'history'" size="'xs'" style="margin-bottom: 2px"></icon>&nbsp;&nbsp;Restore
</a>
<a class="btn btn-outline-disabled btn-small" ng-show="revision.version === ctrl.dashboard.version">
<i class="fa fa-check"></i>&nbsp;&nbsp;Latest
<icon name="'check'" size="'xs'" style="margin-bottom: 2px"></icon>&nbsp;&nbsp;Latest
</a>
</td>
</tr>
@ -50,26 +63,31 @@
</table>
<div ng-if="ctrl.appending">
<i class="fa fa-spinner fa-spin"></i>
<icon name="'fa fa-spinner'" class="fa-spin"></icon>
<em>Fetching more entries&hellip;</em>
</div>
<div class="gf-form-group">
<div class="gf-form-button-row">
<button type="button"
class="btn gf-form-button btn-inverse"
ng-if="ctrl.revisions.length >= ctrl.limit"
ng-click="ctrl.addToLog()"
ng-disabled="ctrl.isLastPage()">
<button
type="button"
class="btn gf-form-button btn-inverse"
ng-if="ctrl.revisions.length >= ctrl.limit"
ng-click="ctrl.addToLog()"
ng-disabled="ctrl.isLastPage()"
>
Show more versions
</button>
<button type="button"
class="btn btn-primary"
ng-if="ctrl.revisions.length > 1"
ng-disabled="!ctrl.canCompare"
ng-click="ctrl.getDiff(ctrl.diff)"
bs-tooltip="ctrl.canCompare ? '' : 'Select 2 versions to start comparing'" data-placement="bottom">
<i class="fa fa-code-fork" ></i>&nbsp;&nbsp;Compare versions
<button
type="button"
class="btn btn-primary"
ng-if="ctrl.revisions.length > 1"
ng-disabled="!ctrl.canCompare"
ng-click="ctrl.getDiff(ctrl.diff)"
bs-tooltip="ctrl.canCompare ? '' : 'Select 2 versions to start comparing'"
data-placement="bottom"
>
<icon name="'code-branch'"></icon>&nbsp;&nbsp;Compare versions
</button>
</div>
</div>
@ -79,29 +97,31 @@
<div ng-if="ctrl.mode === 'compare'">
<div ng-if="ctrl.loading">
<i class="fa fa-spinner fa-spin"></i>
<icon name="'fa fa-spinner'" class="fa-spin"></icon>
<em>Fetching changes&hellip;</em>
</div>
<div ng-if="!ctrl.loading">
<button type="button"
class="btn btn-danger pull-right"
ng-click="ctrl.restore(ctrl.baseInfo.version)"
ng-if="ctrl.isNewLatest">
<i class="fa fa-history" ></i>&nbsp;&nbsp;Restore to version {{ctrl.baseInfo.version}}
<button
type="button"
class="btn btn-danger pull-right"
ng-click="ctrl.restore(ctrl.baseInfo.version)"
ng-if="ctrl.isNewLatest"
>
<icon name="'history'"></icon>&nbsp;&nbsp;Restore to version {{ctrl.baseInfo.version}}
</button>
<section>
<p class="small muted">
<strong>Version {{ctrl.newInfo.version}}</strong> updated by
<span>{{ctrl.newInfo.createdBy}} </span>
<span>{{ctrl.newInfo.ageString}}</span>
<span> - {{ctrl.newInfo.message}}</span>
<strong>Version {{ctrl.newInfo.version}}</strong> updated by
<span>{{ctrl.newInfo.createdBy}} </span>
<span>{{ctrl.newInfo.ageString}}</span>
<span> - {{ctrl.newInfo.message}}</span>
</p>
<p class="small muted">
<strong>Version {{ctrl.baseInfo.version}}</strong> updated by
<span>{{ctrl.baseInfo.createdBy}} </span>
<span>{{ctrl.baseInfo.ageString}}</span>
<span> - {{ctrl.baseInfo.message}}</span>
<strong>Version {{ctrl.baseInfo.version}}</strong> updated by
<span>{{ctrl.baseInfo.createdBy}} </span>
<span>{{ctrl.baseInfo.ageString}}</span>
<span> - {{ctrl.baseInfo.message}}</span>
</p>
</section>

@ -15,7 +15,7 @@ import { DashNav } from '../components/DashNav';
import { AngularSubMenu } from '../components/SubMenu';
import { DashboardSettings } from '../components/DashboardSettings';
import { PanelEditor } from '../components/PanelEditor/PanelEditor';
import { Alert, CustomScrollbar } from '@grafana/ui';
import { Alert, CustomScrollbar, Icon } from '@grafana/ui';
// Redux
import { initDashboard } from '../state/initDashboard';
import { cleanUpDashboard } from '../state/reducers';
@ -216,7 +216,7 @@ export class DashboardPage extends PureComponent<Props, State> {
return (
<div className="dashboard-loading">
<div className="dashboard-loading__text">
<i className="fa fa-spinner fa-spin" /> {this.props.initPhase}
<Icon name="fa fa-spinner" className="fa-spin" /> {this.props.initPhase}
</div>
</div>
);

@ -320,8 +320,9 @@ exports[`DashboardPage Dashboard is fetching slowly Should render slow init stat
<div
className="dashboard-loading__text"
>
<i
className="fa fa-spinner fa-spin"
<Icon
className="fa-spin"
name="fa fa-spinner"
/>
Fetching

@ -251,6 +251,7 @@ export class PanelChromeAngularUnconnected extends PureComponent<Props, State> {
isEditing={isEditing}
data={data}
updateLocation={updateLocation}
alertState={alertState}
/>
<div className={panelContentClassNames}>
<div ref={element => (this.element = element)} className="panel-height-helper" />

@ -25,6 +25,7 @@ export interface Props {
angularComponent?: AngularComponent | null;
links?: DataLink[];
error?: string;
alertState?: string;
isViewing: boolean;
isEditing: boolean;
data: PanelData;
@ -89,7 +90,7 @@ export class PanelHeader extends Component<Props, State> {
private renderLoadingState(): JSX.Element {
return (
<div className="panel-loading">
<i className="fa fa-spinner fa-spin" />
<Icon className="fa-spin" name="fa fa-spinner" />
</div>
);
}
@ -122,7 +123,7 @@ export class PanelHeader extends Component<Props, State> {
};
render() {
const { panel, scopedVars, error, isViewing, isEditing, data } = this.props;
const { panel, scopedVars, error, isViewing, isEditing, data, alertState } = this.props;
const { menuItems } = this.state;
const title = templateSrv.replaceWithText(panel.title, scopedVars);
@ -162,7 +163,14 @@ export class PanelHeader extends Component<Props, State> {
>
<div className="panel-title">
{Object.values(notices).map(this.renderNotice)}
<span className="icon-gf panel-alert-icon" />
{alertState && (
<Icon
name={alertState === 'alerting' ? 'heart-break' : 'heart'}
className="icon-gf panel-alert-icon"
style={{ marginRight: '4px' }}
size="sm"
/>
)}
<span className="panel-title-text">
{title}
<Icon name="angle-down" className="panel-menu-toggle" />

@ -2,7 +2,7 @@
import React, { PureComponent } from 'react';
// Components
import { CustomScrollbar, PanelOptionsGroup } from '@grafana/ui';
import { CustomScrollbar, PanelOptionsGroup, Icon, IconName } from '@grafana/ui';
import { FadeIn } from 'app/core/components/Animations/FadeIn';
interface Props {
@ -90,7 +90,7 @@ export class EditorTabBody extends PureComponent<Props, State> {
return (
<div className="nav-buttons" key={view.title + view.icon}>
<button className="btn navbar-button" onClick={onClick} disabled={view.disabled}>
{view.icon && <i className={view.icon} />} {view.title}
{view.icon && <Icon name={view.icon as IconName} />} {view.title}
</button>
</div>
);

@ -250,7 +250,7 @@ export class QueriesTab extends PureComponent<Props, State> {
const dsHelp: EditorToolbarView = {
heading: 'Help',
icon: 'fa fa-question',
icon: 'question-circle',
render: this.renderHelp,
};

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save