|
9 | 9 | ********************************************************************************/
|
10 | 10 | import React, { useContext } from 'react';
|
11 | 11 | import { observer } from 'mobx-react-lite';
|
12 |
| -import { Button, DatePicker, Form, Input, InputNumber } from 'antd'; |
13 |
| -import Title from 'antd/lib/typography/Title'; |
| 12 | +import { Button, DatePicker, Form, Input, InputNumber, Typography } from 'antd'; |
14 | 13 |
|
15 | 14 | import { MstContext } from '../../MstContext';
|
16 | 15 | import { RankedTester, rankWith, uiTypeIs } from '../../testers';
|
17 | 16 | import { processViewKindOverride } from '../../Form';
|
18 | 17 | import { applySnapshot, getSnapshot } from 'mobx-state-tree';
|
| 18 | +import { JSONSchema7LDPropertyDefinition } from '@agentlab/sparql-jsld-client'; |
| 19 | + |
| 20 | +const { RangePicker } = DatePicker; |
| 21 | +const { Title } = Typography; |
19 | 22 |
|
20 | 23 | const rangeProps = ['amountValueMoving30', 'revenueMoving30', 'price', 'commentsCount', 'firstParsedAt', 'parsedAt'];
|
21 | 24 |
|
| 25 | +export type JSONSchema7LDPropertyDefinitionWithName = JSONSchema7LDPropertyDefinition & { name: string }; |
| 26 | + |
| 27 | +function isInteger(value: any) { |
| 28 | + return parseInt(value, 10).toString() === value; |
| 29 | +} |
| 30 | + |
| 31 | +function dispatchControl(p: JSONSchema7LDPropertyDefinitionWithName) { |
| 32 | + if (p.type === 'integer') |
| 33 | + return ( |
| 34 | + <Form.Item key={`${p.name}`} label={p.title} tooltip={p.description}> |
| 35 | + <Form.Item |
| 36 | + key={`${p.name}-Min`} |
| 37 | + name={`${p.name}-Min`} |
| 38 | + rules={[ |
| 39 | + { |
| 40 | + type: 'integer', |
| 41 | + message: 'Please input integer!', |
| 42 | + validator: (rule: any, value: string) => |
| 43 | + new Promise( |
| 44 | + (resolve, reject) => |
| 45 | + value === undefined || value === '' || (isInteger(value) ? resolve(value) : reject(rule.message)), |
| 46 | + ), |
| 47 | + }, |
| 48 | + ]} |
| 49 | + style={{ display: 'inline-block', width: 'calc(50% - 10px)' }}> |
| 50 | + <Input style={{ width: '100%' }} /> |
| 51 | + </Form.Item> |
| 52 | + <span style={{ display: 'inline-block', width: '20px', lineHeight: '32px', textAlign: 'center' }}>-</span> |
| 53 | + <Form.Item |
| 54 | + key={`${p.name}-Max`} |
| 55 | + name={`${p.name}-Max`} |
| 56 | + rules={[ |
| 57 | + { |
| 58 | + type: 'integer', |
| 59 | + message: 'Please input integer!', |
| 60 | + validator: (rule: any, value: string) => |
| 61 | + new Promise( |
| 62 | + (resolve, reject) => |
| 63 | + value === undefined || value === '' || (isInteger(value) ? resolve(value) : reject(rule.message)), |
| 64 | + ), |
| 65 | + }, |
| 66 | + ]} |
| 67 | + style={{ display: 'inline-block', width: 'calc(50% - 10px)' }}> |
| 68 | + <Input style={{ width: '100%' }} /> |
| 69 | + </Form.Item> |
| 70 | + </Form.Item> |
| 71 | + ); |
| 72 | + else if (p.type === 'string') { |
| 73 | + if (p.format === 'date-time') { |
| 74 | + return ( |
| 75 | + <Form.Item key={`${p.name}`} label={p.title} tooltip={p.description}> |
| 76 | + <RangePicker |
| 77 | + id={{ |
| 78 | + start: `${p.name}-Min`, |
| 79 | + end: `${p.name}-Max`, |
| 80 | + }} |
| 81 | + style={{ width: '100%' }} |
| 82 | + /> |
| 83 | + </Form.Item> |
| 84 | + ); |
| 85 | + } |
| 86 | + return ( |
| 87 | + <Form.Item key={p.name} name={p.name} label={p.title} tooltip={p.description}> |
| 88 | + <Input /> |
| 89 | + </Form.Item> |
| 90 | + ); |
| 91 | + } |
| 92 | +} |
| 93 | + |
| 94 | +export const QueryFormIRI = 'aldkg:QueryForm'; |
| 95 | + |
| 96 | +export interface QueryFormLocale { |
| 97 | + searchBtnTitle: string; |
| 98 | +} |
| 99 | + |
22 | 100 | export const QueryForm = observer<any>((props) => {
|
23 | 101 | const { store } = useContext(MstContext);
|
| 102 | + const locale: QueryFormLocale = store.getLocaleJs(QueryFormIRI); |
24 | 103 | const [id, collIri, collIriOverride, inCollPath, viewKindElement, viewDescrElement] = processViewKindOverride(
|
25 | 104 | props,
|
26 | 105 | store,
|
@@ -69,96 +148,48 @@ export const QueryForm = observer<any>((props) => {
|
69 | 148 | };
|
70 | 149 | });
|
71 | 150 | console.log('QueryForm - newCond', newCond);
|
72 |
| - |
73 | 151 | applySnapshot(coll.collConstr.entConstrs[0].conditions, newCond);
|
74 | 152 | };
|
75 | 153 |
|
| 154 | + const hiddenProperties: string[] = viewKindElement.options?.hiddenProperties || []; |
| 155 | + const coll = store.rep.getColl(collIri); |
| 156 | + const properties: JSONSchema7LDPropertyDefinitionWithName[] = coll?.collConstr?.entConstrs |
| 157 | + ? Object.entries(coll.collConstr.entConstrs[0].schema?.propertiesJs || {}) |
| 158 | + .filter((e) => !hiddenProperties.includes(e[0])) |
| 159 | + .map((e) => ({ |
| 160 | + name: e[0], |
| 161 | + ...e[1], |
| 162 | + })) |
| 163 | + .sort((e1, e2) => { |
| 164 | + if (e1.order === e2.order) return 0; |
| 165 | + if (e1.order === undefined) return 1; |
| 166 | + if (e2.order === undefined) return -1; |
| 167 | + if (e1.order < e2.order) return -1; |
| 168 | + return 1; |
| 169 | + }) |
| 170 | + : []; |
| 171 | + //console.log('QueryForm', { properties }); |
| 172 | + |
76 | 173 | return (
|
77 |
| - <div style={{ margin: '10px 10px 0 10px' }}> |
78 |
| - <Title level={4}>Поиск товаров</Title> |
| 174 | + <div style={viewKindElement.options?.blockStyle || { margin: '10px' }}> |
| 175 | + {viewKindElement.options.title !== undefined && <Title level={4}>{viewKindElement.options.title}</Title>} |
79 | 176 | <Form
|
80 |
| - layout={'vertical'} |
81 |
| - size={'small'} |
| 177 | + style={{ ...(viewKindElement.options?.formStyle || {}) }} |
| 178 | + layout={viewKindElement.options?.layout || 'vertical'} |
| 179 | + size={viewKindElement.options?.size || 'small'} |
82 | 180 | form={form}
|
83 |
| - initialValues={{ amountValueMoving30Min: 20000, amountValueMoving30Max: 60000 }} |
| 181 | + initialValues={{ ...(viewKindElement.options?.initialValues || {}) }} |
84 | 182 | onFinish={onFinish}>
|
85 |
| - <Form.Item |
86 |
| - label='Название товара' |
87 |
| - name='name' |
88 |
| - tooltip='Фрагмент строки в названии для поиска на английском и/или китайском'> |
89 |
| - <Input /> |
90 |
| - </Form.Item> |
91 |
| - |
92 |
| - <Form.Item |
93 |
| - label='Продажи на 30 дней' |
94 |
| - tooltip='Минимальный и максимальный объем продаж товара в шт или кв. метрах'> |
95 |
| - <Form.Item name='amountValueMoving30Min' style={{ display: 'inline-block', width: 'calc(50% - 10px)' }}> |
96 |
| - <InputNumber style={{ width: '100%' }} /> |
97 |
| - </Form.Item> |
98 |
| - <span style={{ display: 'inline-block', width: '20px', lineHeight: '32px', textAlign: 'center' }}>-</span> |
99 |
| - <Form.Item name='amountValueMoving30Max' style={{ display: 'inline-block', width: 'calc(50% - 10px)' }}> |
100 |
| - <InputNumber style={{ width: '100%' }} /> |
101 |
| - </Form.Item> |
102 |
| - </Form.Item> |
103 |
| - |
104 |
| - <Form.Item label='Выручка на 30 дней' tooltip='Минимальная и максимальная выручка товара в юанях'> |
105 |
| - <Form.Item name='revenueMoving30Min' style={{ display: 'inline-block', width: 'calc(50% - 10px)' }}> |
106 |
| - <InputNumber style={{ width: '100%' }} /> |
107 |
| - </Form.Item> |
108 |
| - <span style={{ display: 'inline-block', width: '20px', lineHeight: '32px', textAlign: 'center' }}>-</span> |
109 |
| - <Form.Item name='revenueMoving30Max' style={{ display: 'inline-block', width: 'calc(50% - 10px)' }}> |
110 |
| - <InputNumber style={{ width: '100%' }} /> |
111 |
| - </Form.Item> |
112 |
| - </Form.Item> |
113 |
| - |
114 |
| - <Form.Item label='Цена товара, юань' tooltip='Минимальная и максимальная цены товара в юанях'> |
115 |
| - <Form.Item name='priceMin' style={{ display: 'inline-block', width: 'calc(50% - 10px)' }}> |
116 |
| - <InputNumber style={{ width: '100%' }} /> |
117 |
| - </Form.Item> |
118 |
| - <span style={{ display: 'inline-block', width: '20px', lineHeight: '32px', textAlign: 'center' }}>-</span> |
119 |
| - <Form.Item name='priceMax' style={{ display: 'inline-block', width: 'calc(50% - 10px)' }}> |
120 |
| - <InputNumber style={{ width: '100%' }} /> |
121 |
| - </Form.Item> |
122 |
| - </Form.Item> |
123 |
| - |
124 |
| - <Form.Item label='Кол-во комментариев' tooltip='Минимальное и максимальное количество отзывов о товаре'> |
125 |
| - <Form.Item name='commentsCountMin' style={{ display: 'inline-block', width: 'calc(50% - 10px)' }}> |
126 |
| - <InputNumber style={{ width: '100%' }} /> |
127 |
| - </Form.Item> |
128 |
| - <span style={{ display: 'inline-block', width: '20px', lineHeight: '32px', textAlign: 'center' }}>-</span> |
129 |
| - <Form.Item name='commentsCountMax' style={{ display: 'inline-block', width: 'calc(50% - 10px)' }}> |
130 |
| - <InputNumber style={{ width: '100%' }} /> |
131 |
| - </Form.Item> |
132 |
| - </Form.Item> |
133 |
| - |
134 |
| - <Form.Item label='Добавлено' tooltip='Диапазон дат первого добавления товара в систему'> |
135 |
| - <Form.Item name='firstParsedAtMin' style={{ display: 'inline-block', width: 'calc(50% - 10px)' }}> |
136 |
| - <DatePicker style={{ width: '100%' }} /> |
137 |
| - </Form.Item> |
138 |
| - <span style={{ display: 'inline-block', width: '20px', lineHeight: '32px', textAlign: 'center' }}>-</span> |
139 |
| - <Form.Item name='firstParsedAtMax' style={{ display: 'inline-block', width: 'calc(50% - 10px)' }}> |
140 |
| - <DatePicker style={{ width: '100%' }} /> |
141 |
| - </Form.Item> |
142 |
| - </Form.Item> |
143 |
| - |
144 |
| - <Form.Item label='Ообновлено' tooltip='Диапазон дат последнего обновления товара в системе'> |
145 |
| - <Form.Item name='parsedAtMin' style={{ display: 'inline-block', width: 'calc(50% - 10px)' }}> |
146 |
| - <DatePicker style={{ width: '100%' }} /> |
147 |
| - </Form.Item> |
148 |
| - <span style={{ display: 'inline-block', width: '20px', lineHeight: '32px', textAlign: 'center' }}>-</span> |
149 |
| - <Form.Item name='parsedAtMax' style={{ display: 'inline-block', width: 'calc(50% - 10px)' }}> |
150 |
| - <DatePicker style={{ width: '100%' }} /> |
151 |
| - </Form.Item> |
152 |
| - </Form.Item> |
| 183 | + {properties.map((p) => dispatchControl(p))} |
153 | 184 |
|
154 | 185 | <Form.Item style={{ marginTop: '16px' }}>
|
155 | 186 | <Button type='primary' htmlType='submit'>
|
156 |
| - Искать товар |
| 187 | + {locale.searchBtnTitle} |
157 | 188 | </Button>
|
158 | 189 | </Form.Item>
|
159 | 190 | </Form>
|
160 | 191 | </div>
|
161 | 192 | );
|
162 | 193 | });
|
163 | 194 |
|
164 |
| -export const antdQueryFormTester: RankedTester = rankWith(2, uiTypeIs('aldkg:QueryForm')); |
| 195 | +export const antdQueryFormTester: RankedTester = rankWith(2, uiTypeIs(QueryFormIRI)); |
0 commit comments