@boarteam/boar-pack-common-frontend 2.7.0 → 2.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@boarteam/boar-pack-common-frontend",
3
- "version": "2.7.0",
3
+ "version": "2.8.1",
4
4
  "description": "Common frontend package for Boar Pack",
5
5
  "repository": "git@github.com:boarteam/boar-pack.git",
6
6
  "author": "Andrew Balakirev <balakirev.andrey@gmail.com>",
@@ -46,5 +46,5 @@
46
46
  "scripts": {
47
47
  "yalc:push": "yalc push"
48
48
  },
49
- "gitHead": "fd26e1cd23414aaf4b2aed44640f2eeb2f84b611"
49
+ "gitHead": "da7dfee327d3713dbc9419e69ae61bf725aba89a"
50
50
  }
@@ -15,6 +15,7 @@ import useContentViewMode, { VIEW_MODE_TYPE } from "./useContentViewMode";
15
15
  import { createStyles } from "antd-style";
16
16
  import { debounce } from "lodash";
17
17
  import { NamePath } from "antd/lib/form/interface";
18
+ import { FieldData } from "rc-field-form/lib/interface";
18
19
 
19
20
  const useStyles = createStyles(({css}) => {
20
21
  return {
@@ -61,7 +62,7 @@ const DescriptionsComponent = <Entity extends Record<string | symbol, any>,
61
62
  CreateDto,
62
63
  UpdateDto,
63
64
  TPathParams>,
64
- ref: React.Ref<DescriptionsRefType>,
65
+ ref: React.Ref<DescriptionsRefType<Entity>>,
65
66
  ) => {
66
67
  const { styles } = useStyles();
67
68
 
@@ -133,6 +134,9 @@ const DescriptionsComponent = <Entity extends Record<string | symbol, any>,
133
134
  form.resetFields();
134
135
  },
135
136
  submit: () => handleSubmit(),
137
+ setFieldErrors: (fields: FieldData<Entity>[]) => {
138
+ form.setFields(fields)
139
+ }
136
140
  }));
137
141
 
138
142
  const onValuesChange = debounce((changedValues, allValues) => {
@@ -237,8 +241,7 @@ const DescriptionsComponent = <Entity extends Record<string | symbol, any>,
237
241
  <Result
238
242
  status="404"
239
243
  title="404"
240
- subTitle="The instrument is not found."
241
- extra={<Button type="primary" href={'/liquidity/ecn-instruments'}>See list of instruments</Button>}
244
+ subTitle="The entity is not found."
242
245
  />
243
246
  );
244
247
  }
@@ -4,6 +4,7 @@ import { RowEditableConfig } from "@ant-design/pro-utils";
4
4
  import { QueryJoin } from "@nestjsx/crud-request";
5
5
  import { ProColumns } from "@ant-design/pro-components";
6
6
  import { ProDescriptionsProps } from "@ant-design/pro-descriptions";
7
+ import { FieldData } from "rc-field-form/lib/interface";
7
8
 
8
9
  export type TGetOneParams = {
9
10
  /**
@@ -23,9 +24,10 @@ export type TDescriptionGetRequestParams = {
23
24
  join?: QueryJoin | QueryJoin[];
24
25
  };
25
26
 
26
- export type DescriptionsRefType = {
27
+ export type DescriptionsRefType<Entity> = {
27
28
  reset: () => void;
28
29
  submit: () => void;
30
+ setFieldErrors: (fields: FieldData<Entity>[]) => void;
29
31
  };
30
32
 
31
33
  export type TDescriptionsProps<Entity, CreateDto, UpdateDto, TPathParams = object> = {
@@ -49,7 +51,7 @@ export type TDescriptionsProps<Entity, CreateDto, UpdateDto, TPathParams = objec
49
51
  params?: TDescriptionGetRequestParams,
50
52
  columns: ProColumns<Entity>[],
51
53
  onEntityChange?: (entity: Entity | null) => void;
52
- ref?: React.Ref<DescriptionsRefType>,
54
+ ref?: React.Ref<DescriptionsRefType<Entity>>,
53
55
  } & Omit<ProDescriptionsProps<Entity>, 'columns'>;
54
56
 
55
57
  export type TDescriptionsCreateModalProps<Entity> = Omit<ProDescriptionsProps<Entity>, 'columns'> & {
@@ -1,6 +1,5 @@
1
- import { ProFormSelectProps } from "@ant-design/pro-form/lib/components/Select";
1
+ import { ProFormSelect, ProFormSelectProps } from "@ant-design/pro-components";
2
2
  import { useState } from "react";
3
- import { ProFormSelect } from "@ant-design/pro-form";
4
3
 
5
4
  type RelationSelectProps<T> = ProFormSelectProps & {
6
5
  selectedItem: T | null | undefined,
@@ -44,10 +43,8 @@ export const RelationSelect = function<T>({
44
43
  showSearch
45
44
  mode={'single'}
46
45
  request={request}
46
+ className='relational-select'
47
47
  formItemProps={{
48
- // correct color for invalid relational fields (#64)
49
- // @ts-ignore-next-line
50
- validateStatus: rest['aria-invalid'] === 'true' ? 'error' : 'success',
51
48
  style: {
52
49
  margin: 0,
53
50
  display: 'inline-block',
@@ -1,6 +1,6 @@
1
1
  import { ProColumns } from "@ant-design/pro-components";
2
2
  import { Button, Modal } from "antd";
3
- import { useRef } from "react";
3
+ import { MutableRefObject, useRef } from "react";
4
4
  import { Descriptions, DescriptionsRefType } from "../Descriptions";
5
5
  import { buildFieldsFromColumnsForDescriptionsDisplay } from "./tableTools";
6
6
 
@@ -23,7 +23,7 @@ export interface CreateEntityModalProps<Entity> {
23
23
  * Called when the form is submitted.
24
24
  * Receives the validated form data.
25
25
  */
26
- onSubmit: (data: any) => Promise<void>;
26
+ onSubmit: (data: any, descriptionsRef: MutableRefObject<DescriptionsRefType<Entity>>) => Promise<void>;
27
27
  }
28
28
 
29
29
  export function CreateEntityModal<
@@ -41,7 +41,7 @@ export function CreateEntityModal<
41
41
  onCancel,
42
42
  onSubmit,
43
43
  }: CreateEntityModalProps<Entity>) {
44
- const descriptionsRef = useRef<DescriptionsRefType>(null);
44
+ const descriptionsRef = useRef<DescriptionsRefType<Entity>>(null);
45
45
 
46
46
  // Calculate the editable keys from the columns and idColumnName
47
47
  const editableKeys = [...buildFieldsFromColumnsForDescriptionsDisplay(columns, idColumnName)];
@@ -74,7 +74,7 @@ export function CreateEntityModal<
74
74
  labelStyle={{ width: '15%' }}
75
75
  contentStyle={{ width: '25%' }}
76
76
  canEdit={true}
77
- onCreate={onSubmit}
77
+ onCreate={(data) => onSubmit(data, descriptionsRef)}
78
78
  editable={{
79
79
  editableKeys,
80
80
  actionRender: () => [],
@@ -196,7 +196,7 @@ const Table = <Entity extends Record<string | symbol, any>,
196
196
  bordered
197
197
  search={false}
198
198
  editable={editableConfig}
199
- toolBarRender={(...args) => [
199
+ toolBarRender={toolBarRender === false ? false : (...args) => [
200
200
  columnsSetSelect?.() || null,
201
201
  !viewOnly && onUpdateMany
202
202
  ? bulkEditButton
@@ -205,7 +205,7 @@ const Table = <Entity extends Record<string | symbol, any>,
205
205
  ? bulkDeleteButton
206
206
  : null,
207
207
  !viewOnly && createButton || null,
208
- !viewOnly && importButton || null,
208
+ !viewOnly && onImport && importButton || null,
209
209
  exportUrl && exportButton || null,
210
210
  ...toolBarRender && toolBarRender(...args) || [],
211
211
  ]}
@@ -97,6 +97,7 @@ export const Operators = {
97
97
  lowerOrEquals: CondOperator.LOWER_THAN_EQUALS,
98
98
  isNull: CondOperator.IS_NULL,
99
99
  notNull: CondOperator.NOT_NULL,
100
+ starts: CondOperator.STARTS,
100
101
  } as const;
101
102
 
102
103
  export function applyKeywordToSearch(
@@ -5,6 +5,8 @@ import { PlusOutlined } from "@ant-design/icons";
5
5
  import { FormattedMessage } from "react-intl";
6
6
  import type { SizeType } from "antd/es/config-provider/SizeContext";
7
7
  import { CreateEntityModal, CreateEntityModalProps } from "./CreateEntityModal";
8
+ import { DescriptionsRefType } from "../Descriptions";
9
+ import { ApiError } from '../../tools'
8
10
 
9
11
  let creatingRecordsCount = 0;
10
12
  export const KEY_SYMBOL = Symbol('key');
@@ -41,7 +43,7 @@ export function useCreation<Entity, CreateDto, TPathParams = {}>({
41
43
  } & Omit<CreateEntityModalProps<Entity>, 'onSubmit' | 'onCancel' | 'entity'>) {
42
44
  const [createPopupData, setCreatePopupData] = useState<Partial<Entity> | undefined>();
43
45
 
44
- const onCreateSubmit = async (data: Partial<Entity>) => {
46
+ const onCreateSubmit = async (data: Partial<Entity>, descriptionsRef: MutableRefObject<DescriptionsRefType<Entity>>) => {
45
47
  try {
46
48
  await onCreate?.({
47
49
  ...pathParams,
@@ -54,6 +56,22 @@ export function useCreation<Entity, CreateDto, TPathParams = {}>({
54
56
  await actionRef?.current?.reload();
55
57
  } catch (e) {
56
58
  console.error(e);
59
+
60
+ // Handle common error
61
+ if (e.body && e.body.statusCode && e.body.errors) {
62
+ const error = e as ApiError;
63
+ const { statusCode, errors } = error.body;
64
+ // Validation error. Highlight corresponding form fields
65
+ if (statusCode === 400) {
66
+ const formErrors = errors.map(error => ({
67
+ name: error.field,
68
+ errors: [error.message],
69
+ }));
70
+
71
+ // @ts-ignore
72
+ descriptionsRef.current.setFieldErrors(formErrors);
73
+ }
74
+ }
57
75
  }
58
76
  };
59
77
 
@@ -5,6 +5,7 @@ import { Button, Tooltip } from "antd";
5
5
  import { DeleteOutlined, StopOutlined } from "@ant-design/icons";
6
6
  import { FormattedMessage, useIntl } from "react-intl";
7
7
  import React, { useState } from "react";
8
+ import { isRecordNew } from "./useCreation";
8
9
 
9
10
  export function useEditableTable<Entity, CreateDto, UpdateDto, TPathParams = {}>(
10
11
  {
@@ -68,6 +69,7 @@ export function useEditableTable<Entity, CreateDto, UpdateDto, TPathParams = {}>
68
69
  }
69
70
  },
70
71
  async onDelete(id, row) {
72
+ if (isRecordNew(row)) return;
71
73
  await onDelete({ ...row, ...pathParams });
72
74
  },
73
75
  deletePopconfirmMessage: intl.formatMessage({ id: 'table.deletePopconfirmMessage' }),
@@ -0,0 +1,18 @@
1
+ // Should be synced with common-backend/src/tools/ApiError.ts
2
+ type TApiErrorBodyType = {
3
+ statusCode: number
4
+ message: string
5
+ errors: {
6
+ field: string,
7
+ message: string
8
+ }[]
9
+ }
10
+
11
+ // Copied from api-client/generated/core/ApiError.ts
12
+ export class ApiError extends Error {
13
+ public readonly url: string;
14
+ public readonly status: number;
15
+ public readonly statusText: string;
16
+ public readonly body: TApiErrorBodyType;
17
+ public readonly request: any;
18
+ }
@@ -3,3 +3,4 @@ export * from './useFullscreen';
3
3
  export * from './numberTools';
4
4
  export * from './useTabs';
5
5
  export * from './WebsocketClient';
6
+ export * from './ApiError'