Commit 196f8503 by Peter Holmberg Committed by GitHub

grafana/ui: Add Time of day picker (#18894)

* Adding DashboardPicker component

* fix prop names

* fix prop names pt2

* add component and modify utils

* add showHour prop

* add minuteStep to TimeOfDayPicker, add value to DashboardPicker

* fix for dashboard picker, missed adding file

* Adding story

* add another story for hiding hour and style fixes

* fix these generated files

* fixes after review

* rename current value

* fix type issue on onChange

* fix story
parent 7b856ae0
import { TimeZone } from '../types/time';
/* tslint:disable:import-blacklist ban ban-types */
import moment, { MomentInput, DurationInputArg1 } from 'moment';
import moment, { Moment, MomentInput, DurationInputArg1 } from 'moment';
export interface DateTimeBuiltinFormat {
__momentBuiltinFormatBrand: any;
}
......@@ -72,6 +71,7 @@ export interface DateTime extends Object {
utc: () => DateTime;
utcOffset: () => number;
hour?: () => number;
minute?: () => number;
}
export const setLocale = (language: string) => {
......@@ -98,6 +98,10 @@ export const dateTime = (input?: DateTimeInput, formatInput?: FormatInput): Date
return moment(input as MomentInput, formatInput) as DateTime;
};
export const dateTimeAsMoment = (input?: DateTimeInput) => {
return dateTime(input) as Moment;
};
export const dateTimeForTimeZone = (
timezone?: TimeZone,
input?: DateTimeInput,
......
......@@ -34,6 +34,7 @@
"lodash": "4.17.14",
"moment": "2.24.0",
"papaparse": "4.6.3",
"rc-time-picker": "^3.7.2",
"react": "16.8.6",
"react-calendar": "2.18.1",
"react-color": "2.17.0",
......
import React from 'react';
import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import { TimeOfDayPicker } from './TimeOfDayPicker';
import { UseState } from '../../utils/storybook/UseState';
import { withCenteredStory } from '../../utils/storybook/withCenteredStory';
import { dateTime } from '@grafana/data';
const TimeOfDayPickerStories = storiesOf('UI/TimeOfDayPicker', module);
TimeOfDayPickerStories.addDecorator(withCenteredStory);
TimeOfDayPickerStories.add('default', () => {
return (
<UseState
initialState={{
value: dateTime(Date.now()),
}}
>
{(value, updateValue) => {
return (
<TimeOfDayPicker
onChange={newValue => {
action('on selected')(newValue);
updateValue({ value: newValue });
}}
value={value.value}
/>
);
}}
</UseState>
);
});
TimeOfDayPickerStories.add('only minutes', () => {
return (
<UseState initialState={{ value: dateTime(Date.now()) }}>
{(value, updateValue) => {
return (
<TimeOfDayPicker
onChange={newValue => {
action('on selected')(newValue);
updateValue({ value: newValue });
}}
value={value.value}
showHour={false}
/>
);
}}
</UseState>
);
});
import React, { FC } from 'react';
import RcTimePicker from 'rc-time-picker';
import { dateTime, DateTime, dateTimeAsMoment } from '@grafana/data';
interface Props {
onChange: (value: DateTime) => void;
value: DateTime;
showHour?: boolean;
minuteStep?: number;
}
export const TimeOfDayPicker: FC<Props> = ({ minuteStep = 1, showHour = true, onChange, value }) => {
return (
<div>
<RcTimePicker
defaultValue={dateTimeAsMoment()}
onChange={(value: any) => onChange(dateTime(value))}
allowEmpty={false}
showSecond={false}
value={dateTimeAsMoment(value)}
showHour={showHour}
minuteStep={minuteStep}
/>
</div>
);
};
......@@ -4,12 +4,12 @@ import { action } from '@storybook/addon-actions';
import { TimePicker } from './TimePicker';
import { UseState } from '../../utils/storybook/UseState';
import { withRighAlignedStory } from '../../utils/storybook/withRightAlignedStory';
import { withRightAlignedStory } from '../../utils/storybook/withRightAlignedStory';
import { TimeFragment, dateTime } from '@grafana/data';
const TimePickerStories = storiesOf('UI/TimePicker', module);
TimePickerStories.addDecorator(withRighAlignedStory);
TimePickerStories.addDecorator(withRightAlignedStory);
TimePickerStories.add('default', () => {
return (
......
@import '../../node_modules/rc-time-picker/assets/index.css';
.rc-time-picker-input,
.rc-time-picker-panel-input-wrap,
.rc-time-picker-panel-inner {
background-color: $input-bg;
color: $input-color;
border-color: $input-border-color;
font-size: $font-size-base;
}
.rc-time-picker-input {
padding: $input-padding;
height: $input-height;
}
.rc-time-picker-panel {
width: 176px;
}
.rc-time-picker-panel-select {
width: 50%;
&:only-child {
width: 100%;
}
.rc-time-picker-panel-select-option-selected {
background-color: $menu-dropdown-hover-bg;
}
li:hover {
background-color: $menu-dropdown-hover-bg;
}
}
.rc-time-picker-panel-narrow {
max-width: none;
}
......@@ -14,3 +14,4 @@
@import 'BarGauge/BarGauge';
@import 'RefreshPicker/RefreshPicker';
@import 'TimePicker/TimePicker';
@import 'TimePicker/TimeOfDayPicker';
......@@ -35,6 +35,7 @@ export { StatsPicker } from './StatsPicker/StatsPicker';
export { Input, InputStatus } from './Input/Input';
export { RefreshPicker } from './RefreshPicker/RefreshPicker';
export { TimePicker } from './TimePicker/TimePicker';
export { TimeOfDayPicker } from './TimePicker/TimeOfDayPicker';
export { List } from './List/List';
// Renderless
......
......@@ -17,4 +17,4 @@ const RightAlignedStory: React.FunctionComponent<{}> = ({ children }) => {
);
};
export const withRighAlignedStory = (story: RenderFunction) => <RightAlignedStory>{story()}</RightAlignedStory>;
export const withRightAlignedStory = (story: RenderFunction) => <RightAlignedStory>{story()}</RightAlignedStory>;
import React, { PureComponent } from 'react';
import { AsyncSelect } from '@grafana/ui';
import { SelectableValue } from '@grafana/data';
import { debounce } from 'lodash';
import { getBackendSrv } from 'app/core/services/backend_srv';
import { DashboardSearchHit, DashboardDTO } from 'app/types';
......@@ -7,6 +8,7 @@ import { DashboardSearchHit, DashboardDTO } from 'app/types';
export interface Props {
className?: string;
onSelected: (dashboard: DashboardDTO) => void;
currentDashboardId: SelectableValue<number>;
}
export interface State {
......@@ -36,7 +38,7 @@ export class DashboardPicker extends PureComponent<Props, State> {
.then((result: DashboardSearchHit[]) => {
const dashboards = result.map((item: DashboardSearchHit) => {
return {
id: item.uid,
id: item.id,
value: item.id,
label: `${item.folderTitle ? item.folderTitle : 'General'}/${item.title}`,
};
......@@ -48,7 +50,7 @@ export class DashboardPicker extends PureComponent<Props, State> {
};
render() {
const { className, onSelected } = this.props;
const { className, onSelected, currentDashboardId } = this.props;
const { isLoading } = this.state;
return (
......@@ -63,6 +65,7 @@ export class DashboardPicker extends PureComponent<Props, State> {
onChange={onSelected}
placeholder="Select dashboard"
noOptionsMessage={() => 'No dashboards found'}
value={currentDashboardId}
/>
</div>
</div>
......
diff a/public/sass/_variables.dark.generated.scss b/public/sass/_variables.dark.generated.scss (rejected hunks)
@@ -94,2 +94,2 @@ $textShadow: none;
-$brand-gradient-horizontal: linear-gradient(to right, #f05a28 30%, #fbca0a 99%);
-$brand-gradient-vertical: linear-gradient(#f05a28 30%, #fbca0a 99%);
+$brand-gradient-horizontal: linear-gradient(to right, #F05A28 30%, #FBCA0A 99%);
+$brand-gradient-vertical: linear-gradient(#F05A28 30%, #FBCA0A 99%);
diff a/public/sass/_variables.light.generated.scss b/public/sass/_variables.light.generated.scss (rejected hunks)
@@ -86,2 +86,2 @@ $text-shadow-faint: none;
-$brand-gradient-horizontal: linear-gradient(to right, #f05a28 30%, #fbca0a 99%);
-$brand-gradient-vertical: linear-gradient(#f05a28 30%, #fbca0a 99%);
+$brand-gradient-horizontal: linear-gradient(to right, #F05A28 30%, #FBCA0A 99%);
+$brand-gradient-vertical: linear-gradient(#F05A28 30%, #FBCA0A 99%);
......@@ -12068,7 +12068,7 @@ module-alias@2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/module-alias/-/module-alias-2.2.0.tgz#a2e32275381642252bf0c51405f7a09a367479b5"
moment@2.24.0:
moment@2.24.0, moment@2.x:
version "2.24.0"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b"
......@@ -14629,7 +14629,7 @@ qw@~1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/qw/-/qw-1.0.1.tgz#efbfdc740f9ad054304426acb183412cc8b996d4"
raf@^3.1.0, raf@^3.4.0:
raf@^3.1.0, raf@^3.4.0, raf@^3.4.1:
version "3.4.1"
resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.1.tgz#0742e99a4a6552f445d73e3ee0328af0ff1ede39"
dependencies:
......@@ -14722,6 +14722,18 @@ rc-cascader@0.14.0:
shallow-equal "^1.0.0"
warning "^4.0.1"
rc-time-picker@^3.7.2:
version "3.7.2"
resolved "https://registry.yarnpkg.com/rc-time-picker/-/rc-time-picker-3.7.2.tgz#fabe5501adf1374d31a2d3b47f1ba89fc2dc2467"
integrity sha512-UVWO9HXGyZoM4I2THlJsEAFcZQz+tYwdcpoHXCEFZsRLz9L2+7vV4EMp9Wa3UrtzMFEt83qSAX/90dCJeKl9sg==
dependencies:
classnames "2.x"
moment "2.x"
prop-types "^15.5.8"
raf "^3.4.1"
rc-trigger "^2.2.0"
react-lifecycles-compat "^3.0.4"
rc-trigger@^2.2.0:
version "2.6.2"
resolved "https://registry.yarnpkg.com/rc-trigger/-/rc-trigger-2.6.2.tgz#a9c09ba5fad63af3b2ec46349c7db6cb46657001"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment