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

Add Datetime Picker to form and update Grafana dependencies for components package #38

Merged
merged 2 commits into from
Apr 25, 2024
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
1,248 changes: 507 additions & 741 deletions package-lock.json

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions packages/components/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Change Log

## 1.9.0 (2024-04-05)

### Features

- Add Datetime Picker to form and update Grafana dependencies for components package (#38)

## 1.8.2 (2024-04-18)

### Bugfixes
Expand Down
6 changes: 3 additions & 3 deletions packages/components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
"author": "Volkov Labs",
"dependencies": {
"@emotion/css": "^11.11.2",
"@grafana/data": "^10.2.1",
"@grafana/ui": "^10.2.1",
"@grafana/data": "^10.4.2",
"@grafana/ui": "^10.4.2",
"classnames": "^2.5.1",
"rc-slider": "^10.5.0",
"rc-tooltip": "^6.2.0"
Expand Down Expand Up @@ -86,5 +86,5 @@
"typecheck": "tsc --emitDeclarationOnly false --noEmit"
},
"types": "dist/index.d.ts",
"version": "1.8.2"
"version": "1.9.0"
}
20 changes: 19 additions & 1 deletion packages/components/src/__mocks__/@grafana/ui.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { SelectableValue } from '@grafana/data';
import { dateTime, SelectableValue } from '@grafana/data';
import React from 'react';

const actual = jest.requireActual('@grafana/ui');
Expand Down Expand Up @@ -39,14 +39,14 @@
...restProps
}) => (
<select
onChange={(event: any) => {

Check warning on line 42 in packages/components/src/__mocks__/@grafana/ui.tsx

View workflow job for this annotation

GitHub Actions / build

Unexpected any. Specify a different type
if (onChange) {
if (isMulti) {
const newOptions = allowCustomValue
? event.target.values.map((value: string) => ({
value,
}))
: options.filter((option: any) => event.target.values.includes(option.value));

Check warning on line 49 in packages/components/src/__mocks__/@grafana/ui.tsx

View workflow job for this annotation

GitHub Actions / build

Unexpected any. Specify a different type
onChange(newOptions);
} else {
const plainOptions = options.reduce(
Expand All @@ -54,7 +54,7 @@
[]
);
// eslint-disable-next-line eqeqeq
onChange(plainOptions.find((option: any) => option.value == event.target.value));

Check warning on line 57 in packages/components/src/__mocks__/@grafana/ui.tsx

View workflow job for this annotation

GitHub Actions / build

Unexpected any. Specify a different type
}
}
}}
Expand All @@ -80,7 +80,7 @@
(acc: SelectableValue[], option: SelectableValue) => acc.concat(option.options ? option.options : option),
[]
)
).map(({ label, value }: any) => (

Check warning on line 83 in packages/components/src/__mocks__/@grafana/ui.tsx

View workflow job for this annotation

GitHub Actions / build

Unexpected any. Specify a different type
<option key={value} value={value}>
{label}
</option>
Expand All @@ -89,8 +89,26 @@
)
);

/**
* Mock DatetimePicker component
*/
const DateTimePicker = jest.fn(({ onChange, ...restProps }) => {
return (
<input
data-testid={restProps['data-testid']}
value={restProps.date.toISOString()}
onChange={(event) => {
if (onChange) {
onChange(dateTime(event.target.value));
}
}}
/>
);
});

module.exports = {
...actual,
ColorPicker,
Select,
DateTimePicker,
};
10 changes: 9 additions & 1 deletion packages/components/src/components/Form/Form.story.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ const meta = {
radio: string;
groupField1: string;
groupField2: string;
datetime: string;
}>((builder) =>
builder
.addSlider({
Expand Down Expand Up @@ -114,13 +115,20 @@ const meta = {
row: 'group',
},
})
.addDateTimePicker({
path: 'datetime',
label: 'Datetime',
defaultValue: new Date().toISOString(),
min: new Date().toISOString(),
showSeconds: false,
})
);

return <Form {...args} fields={form.fields} value={form.value} />;
};

return (
<div style={{ width: 600 }}>
<div style={{ width: 600, padding: '20px' }}>
<Preview />
</div>
);
Expand Down
14 changes: 13 additions & 1 deletion packages/components/src/components/Form/Form.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,13 @@ describe('Form', () => {
defaultValue: '#123',
newValue: '#222',
},
{
name: 'datetime picker',
path: 'datetime',
getField: selectors.fieldDatetime,
defaultValue: new Date('2022-02-01T02:02:00').toISOString(),
newValue: new Date('2023-02-02T02:02:00').toISOString(),
},
])(
'Should render $name inline field',
async ({ path, getField, defaultValue, newValue, expectedValue = newValue }) => {
Expand All @@ -287,6 +294,7 @@ describe('Form', () => {
name: string;
age: number;
};
datetime: string;
}>({
variant: 'inline',
getForm: (builder) =>
Expand Down Expand Up @@ -363,7 +371,11 @@ describe('Form', () => {
row: '1,',
},
})
),
)
.addDateTimePicker({
path: 'datetime',
defaultValue: new Date('2022-02-01T02:02:00').toISOString(),
}),
})
);

Expand Down
19 changes: 19 additions & 0 deletions packages/components/src/components/Form/Form.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { dateTime } from '@grafana/data';
import {
CollapsableSection,
ColorPicker,
DateTimePicker,
Field,
InlineField,
InlineFieldRow,
Expand Down Expand Up @@ -281,6 +283,23 @@ export const Form = <TValue extends object>({
);
}

if (field.type === FormFieldType.DATETIME_PICKER) {
return (
<FieldComponent {...fieldProps}>
<DateTimePicker
minDate={field.min ? new Date(field.min) : undefined}
maxDate={field.max ? new Date(field.max) : undefined}
showSeconds={field.showSeconds}
date={dateTime(field.value)}
onChange={(value) => {
field.onChange(value.toISOString());
}}
data-testid={TEST_IDS.form.fieldDatetime()}
/>
</FieldComponent>
);
}

if (field.type === FormFieldType.RADIO) {
return (
<FieldComponent {...fieldProps} data-testid={TEST_IDS.form.fieldRadio(field.fullPath)}>
Expand Down
5 changes: 5 additions & 0 deletions packages/components/src/constants/tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ export const TEST_IDS = {
fieldNumberInput: (name: unknown) => `data-testid form field-number-input-${name}`,
fieldColor: (name: unknown) => `data-testid form field-color-${name}`,
fieldInput: (name: unknown) => `data-testid form field-input-${name}`,
/**
* We should use default value for date-time-picker without data-testid prefix
* https://github.com/grafana/grafana/blob/f43762f39abad43f99b85cbcff6ca30c56f9d75f/packages/grafana-ui/src/components/DateTimePickers/DateTimePicker/DateTimePicker.tsx#L249
*/
fieldDatetime: () => `data-testid date-time-input`,
fieldRadio: (name: unknown) => `data-testid form field-radio-${name}`,
},
};
32 changes: 32 additions & 0 deletions packages/components/src/types/form-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,29 @@ export interface NumberInputOptions<TObject extends object, TValue> extends Base
step?: number;
}

export interface DateTimePickerOptions<TObject extends object, TValue> extends BaseOptions<TObject, TValue> {
/**
* Min
*
* @type {string}
*/
min?: string;

/**
* Max
*
* @type {string}
*/
max?: string;

/**
* Show seconds
*
* @type {boolean}
*/
showSeconds?: boolean;
}

export interface GroupOptions<TObject extends object, TValue extends object> {
/**
* Path
Expand Down Expand Up @@ -271,6 +294,7 @@ export enum FormFieldType {
INPUT = 'input',
NUMBER_INPUT = 'numberInput',
RANGE_SLIDER = 'rangeSlider',
DATETIME_PICKER = 'datetimePicker',
}

/**
Expand Down Expand Up @@ -301,6 +325,9 @@ export type FormField<TObject extends object> =
| ({
type: FormFieldType.NUMBER_INPUT;
} & NumberInputOptions<TObject, TObject[keyof TObject]>)
| ({
type: FormFieldType.DATETIME_PICKER;
} & DateTimePickerOptions<TObject, TObject[keyof TObject]>)
| ({
type: FormFieldType.GROUP;
} & GroupOptions<TObject, IsObject<TObject[keyof TObject]>>)
Expand Down Expand Up @@ -357,6 +384,11 @@ export type RenderFormField<TObject extends object> =
value: number;
onChange: (value: number) => void;
} & NumberInputOptions<TObject, TObject[keyof TObject]>)
| ({
type: FormFieldType.DATETIME_PICKER;
value: string;
onChange: (value: string) => void;
} & DateTimePickerOptions<TObject, TObject[keyof TObject]>)
) & {
showIf: () => boolean;
disableIf: () => boolean;
Expand Down
10 changes: 10 additions & 0 deletions packages/components/src/utils/form-builder.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,16 @@ describe('Form Builder', () => {
expect(form.getValue().color).toEqual('#123');
});

it('Should add datetime picker field', () => {
const date = new Date('2022-02-02');
const form = new FormBuilder<{ datetime: string }>({ path: '', label: '' }).addDateTimePicker({
path: 'datetime',
defaultValue: date.toISOString(),
});

expect(form.getValue().datetime).toEqual(date.toISOString());
});

it('Should add custom field', () => {
const form = new FormBuilder<{ custom: string }>({ path: '', label: '' }).addCustom({
path: 'custom',
Expand Down
12 changes: 12 additions & 0 deletions packages/components/src/utils/form-builder.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
ColorOptions,
CustomOptions,
DateTimePickerOptions,
FormField,
FormFieldType,
HiddenOptions,
Expand Down Expand Up @@ -165,6 +166,17 @@ export class FormBuilder<TObject extends object> {
});
}

/**
* Add Date Time Picker Field
* @param options
*/
addDateTimePicker<TOptions extends DateTimePickerOptions<TObject, TObject[TOptions['path']]>>(options: TOptions) {
return this.addField({
...options,
type: FormFieldType.DATETIME_PICKER,
});
}

/**
* Add Custom Field
* @param options
Expand Down
Loading