Skip to content

Commit

Permalink
Add float field type for keystone-next (#4907)
Browse files Browse the repository at this point in the history
* Added float field type for keystone-next
Based on integer field type with some modifications

* Remove debug marks

* Added changeset

* Fix lint

* Filtering the raw input

Co-authored-by: Mitchell Hamilton <[email protected]>

* Sync serialize-deserialize logic with integer field

Co-authored-by: Mitchell Hamilton <[email protected]>
  • Loading branch information
MurzNN and emmatown authored Feb 23, 2021
1 parent 1e5dc9e commit 53b8b65
Show file tree
Hide file tree
Showing 5 changed files with 156 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .changeset/light-scissors-agree.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@keystone-next/fields': minor
---

Added float field type for keystone-next
1 change: 1 addition & 0 deletions packages-next/fields/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export { text } from './types/text';
export { password } from './types/password';
export { timestamp } from './types/timestamp';
export { integer } from './types/integer';
export { float } from './types/float';
export { mongoId } from './types/mongoId';
export { autoIncrement } from './types/autoIncrement';
export { select } from './types/select';
Expand Down
21 changes: 21 additions & 0 deletions packages-next/fields/src/types/float/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Float } from '@keystonejs/fields';
import type { FieldType, BaseGeneratedListTypes, FieldDefaultValue } from '@keystone-next/types';
import { resolveView } from '../../resolve-view';
import type { FieldConfig } from '../../interfaces';

export type FloatFieldConfig<
TGeneratedListTypes extends BaseGeneratedListTypes
> = FieldConfig<TGeneratedListTypes> & {
isRequired?: boolean;
isIndexed?: boolean;
isUnique?: boolean;
defaultValue?: FieldDefaultValue<string>;
};

export const float = <TGeneratedListTypes extends BaseGeneratedListTypes>(
config: FloatFieldConfig<TGeneratedListTypes> = {}
): FieldType<TGeneratedListTypes> => ({
type: Float,
config,
views: resolveView('float/views'),
});
125 changes: 125 additions & 0 deletions packages-next/fields/src/types/float/views/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/* @jsx jsx */

import { jsx } from '@keystone-ui/core';
import { FieldContainer, FieldLabel, TextInput } from '@keystone-ui/fields';
import { CellLink, CellContainer } from '@keystone-next/admin-ui/components';

import {
CardValueComponent,
CellComponent,
FieldController,
FieldControllerConfig,
FieldProps,
} from '@keystone-next/types';

export const Field = ({ field, value, onChange, autoFocus }: FieldProps<typeof controller>) => (
<FieldContainer>
<FieldLabel>{field.label}</FieldLabel>
{onChange ? (
<TextInput
autoFocus={autoFocus}
onChange={event => onChange(event.target.value.replace(/[^\d\.]/, ''))}
value={value}
/>
) : (
value
)}
</FieldContainer>
);

export const Cell: CellComponent = ({ item, field, linkTo }) => {
let value = item[field.path] + '';
return linkTo ? <CellLink {...linkTo}>{value}</CellLink> : <CellContainer>{value}</CellContainer>;
};
Cell.supportsLinkTo = true;

export const CardValue: CardValueComponent = ({ item, field }) => {
return (
<FieldContainer>
<FieldLabel>{field.label}</FieldLabel>
{item[field.path]}
</FieldContainer>
);
};

export const controller = (config: FieldControllerConfig): FieldController<string, string> => {
return {
path: config.path,
label: config.label,
graphqlSelection: config.path,
defaultValue: '',
deserialize: data => {
const value = data[config.path];
return typeof value === 'number' ? value + '' : '';
},
serialize: value => ({ [config.path]: value === '' ? null : parseFloat(value) }),
filter: {
Filter(props) {
return (
<TextInput
onChange={event => {
props.onChange(event.target.value.replace(/[^\d\.,\s]/g, ''));
}}
value={props.value}
autoFocus={props.autoFocus}
/>
);
},

graphql: ({ type, value }) => {
const key = type === 'is' ? config.path : `${config.path}_${type}`;
const valueWithoutWhitespace = value.replace(/\s/g, '');

return {
[key]: ['in', 'not_in'].includes(type)
? valueWithoutWhitespace.split(',').map(i => parseFloat(i))
: parseFloat(valueWithoutWhitespace),
};
},
Label({ label, value, type }) {
let renderedValue = value;
if (['in', 'not_in'].includes(type)) {
renderedValue = value
.split(',')
.map(value => value.trim())
.join(', ');
}
return `${label.toLowerCase()}: ${renderedValue}`;
},
types: {
is: {
label: 'Is exactly',
initialValue: '',
},
not: {
label: 'Is not exactly',
initialValue: '',
},
gt: {
label: 'Is greater than',
initialValue: '',
},
lt: {
label: 'Is less than',
initialValue: '',
},
gte: {
label: 'Is greater than or equal to',
initialValue: '',
},
lte: {
label: 'Is less than or equal to',
initialValue: '',
},
in: {
label: 'Is one of',
initialValue: '',
},
not_in: {
label: 'Is not one of',
initialValue: '',
},
},
},
};
};
4 changes: 4 additions & 0 deletions packages-next/fields/types/float/views/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"main": "dist/fields.cjs.js",
"module": "dist/fields.esm.js"
}

1 comment on commit 53b8b65

@vercel
Copy link

@vercel vercel bot commented on 53b8b65 Feb 23, 2021

Choose a reason for hiding this comment

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

Please sign in to comment.