Skip to content

Commit

Permalink
Merge branch 'master' into renovate/eslint-plugin-react-7.x
Browse files Browse the repository at this point in the history
  • Loading branch information
timleslie authored Sep 23, 2020
2 parents eb0cbac + c010c82 commit 0c9e636
Show file tree
Hide file tree
Showing 6 changed files with 219 additions and 32 deletions.
97 changes: 88 additions & 9 deletions packages-next/admin-ui/src/pages/ListPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,67 @@ import { LinkIcon } from '@keystone-ui/icons/icons/LinkIcon';
import { PageContainer } from '../components/PageContainer';
import { useList } from '../KeystoneContext';
import { useRouter, Link } from '../router';
import { JSONValue } from '@keystone-spike/types';

type ListPageProps = {
listKey: string;
};
type Filter = { field: string; type: string; value: JSONValue };

export const ListPage = ({ listKey }: ListPageProps) => {
const list = useList(listKey);

const { query } = useRouter();
const selectedFieldsFromUrl = query.fields || '';
const selectedFieldsFromUrl = typeof query.fields === 'string' ? query.fields : '';
const possibleFilters = useMemo(() => {
const possibleFilters: Record<string, { type: string; field: string }> = {};
Object.entries(list.fields).forEach(([fieldPath, field]) => {
if (field.controller.filter) {
Object.keys(field.controller.filter.types).forEach(type => {
possibleFilters[`!${fieldPath}_${type}`] = {
type,
field: fieldPath,
};
});
}
});
console.log(possibleFilters);
return possibleFilters;
}, [list]);
const filters = useMemo(() => {
let filters: Filter[] = [];
Object.keys(query).forEach(key => {
const filter = possibleFilters[key];
const val = query[key];
if (filter && typeof val === 'string') {
let value;
try {
value = JSON.parse(val);
} catch (err) {}
if (val !== undefined) {
filters.push({
...filter,
value,
});
}
}
});

let where = {};

filters.forEach(filter => {
Object.assign(
where,
list.fields[filter.field].controller.filter!.graphql({
type: filter.type,
value: filter.value,
})
);
});

return { filters, where };
}, [query, possibleFilters, list]);

const selectedFields = useMemo(() => {
if (!query.fields) {
return {
Expand All @@ -25,12 +76,12 @@ export const ListPage = ({ listKey }: ListPageProps) => {
};
}
let includeLabel = false;
let fields = (selectedFieldsFromUrl as string).split(',').filter(field => {
let fields = selectedFieldsFromUrl.split(',').filter(field => {
if (field === '_label_') {
includeLabel = true;
return false;
}
return true;
return list.fields[field] !== undefined;
});
return {
fields,
Expand All @@ -46,15 +97,18 @@ export const ListPage = ({ listKey }: ListPageProps) => {
})
.join('\n');
return gql`
query {
items: ${list.gqlNames.listQueryName} {
query($where: ${list.gqlNames.whereInputName}) {
items: ${list.gqlNames.listQueryName}(where: $where) {
id
${selectedFields.includeLabel ? '_label_' : ''}
${selectedGqlFields}
}
}
`;
}, [list, selectedFields])
}, [list, selectedFields]),
{
variables: { where: filters.where },
}
);

const shouldShowNonCellLink =
Expand All @@ -79,6 +133,28 @@ export const ListPage = ({ listKey }: ListPageProps) => {
})()
: ' '}
</p>
{filters.filters.length ? (
<p>
Filters:
<ul>
{filters.filters.map(filter => {
const field = list.fields[filter.field];
const { [`!${filter.field}_${filter.type}`]: _ignore, ...queryToKeep } = query;
return (
<li key={`${filter.field}_${filter.type}`}>
{field.label}{' '}
{field.controller.filter!.format({
label: field.controller.filter!.types[filter.type].label,
type: filter.type,
value: filter.value,
})}
<Link href={{ query: queryToKeep }}>Remove</Link>
</li>
);
})}
</ul>
</p>
) : null}
{error ? (
'Error...'
) : data ? (
Expand All @@ -98,7 +174,10 @@ export const ListPage = ({ listKey }: ListPageProps) => {
<tr key={item.id}>
{selectedFields.includeLabel && (
<td>
<Link href={`/${list.path}/[id]`} as={`/${list.path}/${item.id}`}>
<Link
href={`/${list.path}/[id]`}
as={`/${list.path}/${encodeURIComponent(item.id)}`}
>
{item._label_}
</Link>
</td>
Expand All @@ -108,7 +187,7 @@ export const ListPage = ({ listKey }: ListPageProps) => {
<Link
css={{ textDecoration: 'none' }}
href={`/${list.path}/[id]`}
as={`/${list.path}/${item.id}`}
as={`/${list.path}/${encodeURIComponent(item.id)}`}
>
<LinkIcon aria-label="Go to item" />
</Link>
Expand All @@ -125,7 +204,7 @@ export const ListPage = ({ listKey }: ListPageProps) => {
i === 0 && !selectedFields.includeLabel && Cell.supportsLinkTo
? {
href: `/${list.path}/[id]`,
as: `/${list.path}/${item.id}`,
as: `/${list.path}/${encodeURIComponent(item.id)}`,
}
: undefined
}
Expand Down
32 changes: 29 additions & 3 deletions packages-next/fields/src/types/checkbox/views/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@

import { jsx, useTheme } from '@keystone-ui/core';
import { FieldContainer, Checkbox } from '@keystone-ui/fields';
import { CellComponent, FieldProps, makeController } from '@keystone-spike/types';
import {
CellComponent,
FieldController,
FieldControllerConfig,
FieldProps,
} from '@keystone-spike/types';
import { Fragment } from 'react';

export const Field = ({ field, value, onChange }: FieldProps<typeof controller>) => {
Expand All @@ -27,7 +32,9 @@ export const Cell: CellComponent = ({ item, path }) => {
return <Fragment>{item[path] + ''}</Fragment>;
};

export const controller = makeController(config => {
type CheckboxController = FieldController<boolean, boolean>;

export const controller = (config: FieldControllerConfig): CheckboxController => {
return {
path: config.path,
label: config.label,
Expand All @@ -45,5 +52,24 @@ export const controller = makeController(config => {
validate() {
// Can throw a FieldError
},
filter: {
graphql({ type, value }) {
const key = type === 'is' ? `${config.path}` : `${config.path}_${type}`;
return { [key]: value };
},
format({ label }) {
return label;
},
types: {
is: {
label: 'is',
initialValue: true,
},
not: {
label: 'is not',
initialValue: true,
},
},
},
};
});
};
27 changes: 24 additions & 3 deletions packages-next/fields/src/types/password/views/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@
import { jsx } from '@keystone-ui/core';
import { FieldContainer, FieldLabel, TextInput } from '@keystone-ui/fields';

import { CellComponent, FieldProps, makeController } from '@keystone-spike/types';
import {
CellComponent,
FieldController,
FieldControllerConfig,
FieldProps,
} from '@keystone-spike/types';
import { Fragment } from 'react';

export const Field = ({ field, value, onChange }: FieldProps<typeof controller>) => (
Expand All @@ -23,13 +28,29 @@ export const Cell: CellComponent = ({ item, path }) => {
return <Fragment>{item[`${path}_is_set`] ? 'Is set' : 'Is not set'}</Fragment>;
};

export const controller = makeController(config => {
type PasswordController = FieldController<string, boolean>;

export const controller = (config: FieldControllerConfig): PasswordController => {
return {
path: config.path,
label: config.label,
graphqlSelection: `${config.path}_is_set`,
defaultValue: '',
deserialize: () => '',
serialize: value => ({ [config.path]: value }),
filter: {
graphql: ({ type, value }) => {
return { [`${config.path}_${type}`]: value };
},
format: ({ value }) => {
return value ? 'is set' : 'is not set';
},
types: {
is_set: {
label: 'Is Set',
initialValue: true,
},
},
},
};
});
};
8 changes: 5 additions & 3 deletions packages-next/fields/src/types/relationship/views/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { jsx, useTheme } from '@keystone-ui/core';
import { FieldContainer, FieldLabel } from '@keystone-ui/fields';

import { FieldProps, makeController } from '@keystone-spike/types';
import { FieldController, FieldControllerConfig, FieldProps } from '@keystone-spike/types';

export const Field = ({ field }: FieldProps<typeof controller>) => {
const { radii, palette } = useTheme();
Expand Down Expand Up @@ -31,7 +31,9 @@ export const Cell = () => {
return null;
};

export const controller = makeController(config => {
type RelationshipController = FieldController<void>;

export const controller = (config: FieldControllerConfig): RelationshipController => {
return {
path: config.path,
label: config.label,
Expand All @@ -40,4 +42,4 @@ export const controller = makeController(config => {
deserialize: () => {},
serialize: () => ({}),
};
});
};
56 changes: 52 additions & 4 deletions packages-next/fields/src/types/text/views/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import { FieldContainer, FieldLabel, TextInput, TextArea } from '@keystone-ui/fi

import {
CellComponent,
FieldController,
FieldControllerConfig,
FieldProps,
makeController,
} from '@keystone-spike/types';
import { Link } from '@keystone-spike/admin-ui/router';
import { Fragment } from 'react';
Expand Down Expand Up @@ -41,14 +41,62 @@ Cell.supportsLinkTo = true;

type Config = FieldControllerConfig<{ isMultiline: boolean }>;

export const controller = makeController((config: Config) => {
export const controller = (
config: Config
): FieldController<string, string> & { isMultiline: boolean } => {
return {
path: config.path,
label: config.label,
graphqlSelection: config.path,
defaultValue: '',
isMultiline: config.fieldMeta.isMultiline,
deserialize: data => data[config.path] || '',
deserialize: data => {
const value = data[config.path];
return typeof value === 'string' ? value : '';
},
serialize: value => ({ [config.path]: value }),
filter: {
graphql: ({ type, value }) => {
const key = type === 'is_i' ? `${config.path}_i` : `${config.path}_${type}`;
return { [key]: value };
},
format: ({ label, value }) => {
return `${label}: "${value}"`;
},
types: {
contains_i: {
label: 'Contains',
initialValue: '',
},
not_contains_i: {
label: 'Does not contain',
initialValue: '',
},
is_i: {
label: 'Is exactly',
initialValue: '',
},
not_i: {
label: 'Is not exactly',
initialValue: '',
},
starts_with_i: {
label: 'Starts with',
initialValue: '',
},
not_starts_with_i: {
label: 'Does not start with',
initialValue: '',
},
ends_with_i: {
label: 'Ends with',
initialValue: '',
},
not_ends_with_i: {
label: 'Does not end with',
initialValue: '',
},
},
},
};
});
};
Loading

0 comments on commit 0c9e636

Please sign in to comment.