# apant

Apollo & Antd tools

## Table of Contents

  * [Installation](#installation)
  * [Live demo](#live-demo)
  * [Usage](#usage)
  * [Working locally with apant](#working-locally-with-apant)
  * [Tests](#tests)


## Usage

```ts
import { TypesContext, TypesRegistry, useTypeList } from "apant";

import client from "./apollo";
import operations from "./gql";
import types from "./types";

const typesRegistry = new TypesRegistry({ types, operations, apollo: client });

const Root = () => (
  <TypesContext.Provider value={typesRegistry}>
    <YourApp />
  </TypesContext.Provider>
);
```
### [TypesRegistryConfiguration](./src/definitions.ts#TypesRegistryConfiguration)
|   Property    |           Description           |                                Type                                | Default |
| :-----------: | :-----------------------------: | :----------------------------------------------------------------: | :-----: |
|    apollo     |     Apollo client instance      |                ApolloClient\<NormalizedCacheObject>                |    -    |
| configuration | GraphQL Operation configuration | Partial<[TypeOperationConfiguration](#TypeOperationConfiguration)> |    -    |
|  operations   |     GraphQL Operation file      |                      { [name: string]: any };                      |    -    |
|     types     |   List of types configuration   |               { [type: string]: TypeConfiguration }                |    -    |


#### example type

```ts
//types/index.ts
import { Foo } from "./Foo";

export default {
  foo
};

// example/src/types/Book.ts
import { TypeConfiguration } from 'apant';

const Book: TypeConfiguration = {
    label: 'title',
    search: 'title',
    admin: {
        route: 'admin/Book',
        searchable: true,
        selectable: true,
        filter(pattern: any) {
            return pattern.rank >= 9;
        },
        columns: () => [
            {
                title: 'Title',
                dataIndex: 'title',
                link: true,
            },
            {
                title: 'Description',
                dataIndex: 'description',
            },
            {
                title: 'Price',
                dataIndex: 'price',
                sorter: {
                    compare: (a: any, b: any) => a.price - b.price,
                },
            },
        ],
    },
    forms: {
        default: {
            props: {
                layout: 'vertical',
            },
            fields: [
                { name: 'title', label: 'Title' },
                { name: 'description', label: 'Description' },
                { name: 'price', label: 'Price', widget:'number' },
                { name: 'rank', label: 'Rank' },
                { name: 'author', label: 'Author',widget: {widget:'select_type', expand:true , type: 'Author'}},
                { name: 'genres', label: 'Genre', widget: {widget:'select_types', expand:true, type: 'Genre'}},
            ],
        },
    },
};
export default Book;
```

### [TypeOperationConfiguration](./src/definitions.ts#TypeOperationConfiguration)
|  Property  |                Description                |                                                                                                        Type                                                                                                        |      Default      |
| :--------: | :---------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :---------------: |
|   admin    |            admin configuration            |                                                                                 [TypeConfigurationAdmin](#TypeConfigurationAdmin)                                                                                  |         -         |
|   forms    | A list of configured forms for this types |                                                                      { [formName: string]: <[FormConfigurationType](#FormConfigurationType) }                                                                      |         -         |
|     id     |  What is the id property for this type?   |                                                                                                       string                                                                                                       |        id         |
|   label    |              For selectType               |                                                                                       string\|() =>string\|React.ReactNode)                                                                                        | '\_name' property |
|  metadata  |  Additional configuration for this type   |                                                                                               { [key: string]: any }                                                                                               |         -         |
| operations |  Operation configuration for given type   |                                                              Partial\<[TypeOperationConfiguration](./src/definitions.ts#TypeOperationConfiguration)>                                                               |         -         |
|   order    |              For SelectType               |                                                                                   order:string\| {[field:string]:'asc'\|'desc'}                                                                                    |       'asc'       |
|   search   |              search in type               | string\|string[] \| ((object:[GraphQLObject](./src/definitions.ts#GraphQLObject),context?:any)=>string)\|{custom:(object:[GraphQLObject](./src/definitions.ts#GraphQLObject),search:string,context?:any)=>boolean} |         -         |
|   select   |     Select type widget configuration      |                                                                                           { label: any; fragment: any };                                                                                           |         -         |

### [TypeConfigurationAdmin](./src/definitions.ts#TypeConfigurationAdmin)
|    Property     |         Description          |                                     Type                                     | Default |
| :-------------: | :--------------------------: | :--------------------------------------------------------------------------: | :-----: |
|     columns     |      the configColumns       |           ()=>Promise<ColumnsType>\|<br>ColumnsType(see AntDesign)           |    -    |
|    creatable    |  allows to create new items  |                                     bool                                     |  true   |
|     filter      |         Filter items         |                            (item:object)=>boolean                            |    -    |
| footerComponent |        Custom footer         | React.ComponentType<[AdminHeaderType](./src/definitions.ts#AdminFooterType)> |    -    |
| headerComponent |        Custom header         | React.ComponentType<[AdminHeaderType](./src/definitions.ts#AdminHeaderType)> |    -    |
|      route      |                              |                                    string                                    |    -    |
|   searchable    | Allow to search in this type |                                     bool                                     |  true   |
|   selectable    |       Allow to select        |                                     bool                                     |  true   |
|      props      |                              |       TableProps<[GraphQLObject](./src/definitions.ts#GraphQLObject)>        |    -    |


### [FormConfigurationType](./src/definitions.ts#FormConfigurationType)
| Property | Description |                                                                                                      Type                                                                                                      | Default |
| :------: | :---------: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-----: |
|  fields  | the fields  |                               [FormEntryType](./src/definitions.ts#FormEntryType)[] \| ((context: [FormContextType](./src/definitions.ts#FormContextType)) => FormEntryType[]);                                |    -    |
|  props   |             |                                 props?: Omit\<FormProps, 'onFinish'> \| ((context: [FormContextType](./src/definitions.ts#FormContextType)) => Omit\<FormProps, 'onFinish'>);                                  |    -    |
| mappers  |             | [FormFieldMapperType](./src/definitions.ts#FormFieldMapperType)[] \| ((context: [FormContextType](./src/definitions.ts#FormContextType)) => [FormFieldMapperType](./src/definitions.ts#FormFieldMapperType)[]) |    -    |


### [FormFieldExtraType](./src/definitions.ts#FormFieldExtraType)
|   Property   |                                  Description                                  |                                       Type                                        | Default |
| :----------: | :---------------------------------------------------------------------------: | :-------------------------------------------------------------------------------: | :-----: |
|     auto     | Should this field be display when the related form is diplayed automatically? |                                       bool                                        |  false  |
|    group     |                        Is the field parts of a group ?                        |                                       bool                                        |  false  |
| initialValue |                What is the initial/default value of the field?                | ((context:[FormContextType](./src/definitions.ts#FormContextType)) => any) \|any; |    -    |
|     list     |                Is this field a list (ie. Form.List from antd)                 |                                       bool                                        |  false  |
|    mapped    |                Should this field be removed before submitting?                |      boolean \| ((context: FormContextType) => boolean \| Promise<boolean>);      |  true   |
|     auto     | Should this field be display when the related form is diplayed automatically? |              boolean \| ((context: FormContextType) => boolean \| );              |  true   |




### Use [AdminType](./src/components/AdminType.tsx#AdminType)


```tsx
<AdminType
  key={type}
  type={type}
  heights={{ offset: 16 }}
  {...getDefaultTableProps()}
  />
```


### Use [Form](./src/components/Form.tsx#Form)


Basic use, if you want further customization, see our [demo](#live-demo).

```tsx

const formConfig = {
  props: { layout: "vertical" },
  fields: [
    {
      name: "name",
      label: "Nom",
      required: true,
      rules: [{ required: true }],
      initialValue: "Ode"
    },
    { name: "firstname", label: "Prénom", initialValue: "Jack" },
    { name: ['position','name'], label: 'Position'},
  ]
};

const object = {
    name: 'Doe',
    city: 'Paris',
    position:{
        name: 'Software Engineer',
        company: 'Google'
    },
};

  //...
  <Form
    config={formConfig}
    onFinish={values => console.log(values)}
    context={{ object }}
    footer={
      <div className="text-center">
        <Button type="primary" htmlType="submit">
          Sauvegarder
        </Button>
      </div>
    }
  />
);
```

|                 Property                 |              Description              |                                                  Type                                                   | Default |
| :--------------------------------------: | :-----------------------------------: | :-----------------------------------------------------------------------------------------------------: | :-----: |
|                 children                 |                                       |      React.ReactNode \|((fields: FormEntryResolvedType[], form: FormInstance) => React ReactNode)       |    -    |
|                  config                  |       Configuration of the form       |                                          FormConfigurationType                                          |    -    |
|                 context                  |          Context of the form          |                  Omit<[FormContextType](./src/definitions.ts#FormContextType), 'form'>                  |    -    |
|                formProps                 |         Additional form Props         |                                         Partial\<FormAntProps>                                          |    -    |
|                  footer                  |              the footer               |                                             React.ReactNode                                             |    -    |
|                  header                  |              the header               |                                             React.ReactNode                                             |    -    |
|                 onValue                  | Process form values before submitting | (values: object, context: [FormContextType](./src/definitions.ts#FormContextType)) => Promise\<object>; |         |
| & <b>Omit\<FormAntProps, 'children'></b> |                                       |                                                                                                         |         |




## Working locally with apant

Working locally with apant relies on `yalc` and `yarn`.

First, you neeed to compile the project.

```bash
$ cd apant
$ yarn
$ yarn build
```

Then, you'll need to publish the project with `yalc`.

```bash
$ yalc publish
apant@xxx published in store.
```

The project is now in the yalc store and is available to use for other project.

### Use the `apant` in your project

To use the library in your local project, you need to link it with `yalc`.

```bash
$ cd myproject/
$ yalc link apant
```

`apant` is now linked to the project.

### Work in realtime

To work and use apant in realtime, we must watch `apant` for change, compile it and publish it the `yalc` store.  
To do so, we use the npm command defined in the `package.json` by

```json
"watch-publish": "tsc-watch --onSuccess \"yalc push\""
```

```bash
$ cd apant/
$ yarn watch-publish
```


## Test

