Autocomplete for tune attributes (#847)
This commit is contained in:
parent
6d42bc12bb
commit
05e51fc3b5
|
@ -110,12 +110,32 @@ const useDb = () => {
|
|||
}
|
||||
};
|
||||
|
||||
const autocomplete = async (attribute: string, search: string) => {
|
||||
try {
|
||||
const items = await client.records.getFullList(Collections.Tunes, 10, {
|
||||
filter: `${attribute} ~ "${search}"`,
|
||||
});
|
||||
|
||||
return Promise.resolve(items as TunesRecordFull[]);
|
||||
} catch (error) {
|
||||
if ((error as ClientResponseError).isAbort) {
|
||||
return Promise.reject(new Error('Cancelled'));
|
||||
}
|
||||
|
||||
Sentry.captureException(error);
|
||||
databaseGenericError(new Error(formatError(error)));
|
||||
|
||||
return Promise.reject(error);
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
updateTune: (tuneId: string, data: TunesRecordPartial): Promise<void> => updateTune(tuneId, data),
|
||||
createTune: (data: TunesRecord): Promise<TunesRecordFull> => createTune(data),
|
||||
getTune: (tuneId: string): Promise<TunesRecordFull | null> => getTune(tuneId),
|
||||
getIni: (tuneId: string): Promise<IniFilesRecordFull | null> => getIni(tuneId),
|
||||
searchTunes: (search: string, page: number, perPage: number): Promise<{ items: TunesRecordFull[]; totalItems: number }> => searchTunes(search, page, perPage),
|
||||
autocomplete: (attribute: string, search: string): Promise<TunesRecordFull[]> => autocomplete(attribute, search),
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ import {
|
|||
Typography,
|
||||
Upload,
|
||||
Form,
|
||||
AutoComplete,
|
||||
} from 'antd';
|
||||
import {
|
||||
PlusOutlined,
|
||||
|
@ -33,6 +34,7 @@ import {
|
|||
GlobalOutlined,
|
||||
EyeOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import debounce from 'lodash.debounce';
|
||||
import { INI } from '@hyper-tuner/ini';
|
||||
import { UploadRequestOption } from 'rc-upload/lib/interface';
|
||||
import { UploadFile } from 'antd/lib/upload/interface';
|
||||
|
@ -138,7 +140,24 @@ const UploadPage = () => {
|
|||
const { currentUser, refreshUser } = useAuth();
|
||||
const navigate = useNavigate();
|
||||
const { fetchTuneFile } = useServerStorage();
|
||||
const { createTune, updateTune, getTune } = useDb();
|
||||
const { createTune, updateTune, getTune, autocomplete } = useDb();
|
||||
|
||||
const [autocompleteOptions, setAutocompleteOptions] = useState<{ [attribute: string]: { value: string }[] }>({});
|
||||
|
||||
const searchAutocomplete = debounce(async (attribute: string, search: string) => {
|
||||
if (search.length === 0) {
|
||||
setAutocompleteOptions((prev) => ({ ...prev, [attribute]: [] }));
|
||||
return;
|
||||
}
|
||||
|
||||
const options = (await autocomplete(attribute, search))
|
||||
.map((record) => record[attribute]);
|
||||
|
||||
// TODO: order by occurrence (more common - higher in the list)
|
||||
const unique = [...new Set(options)].map((value) => ({ value }));
|
||||
|
||||
setAutocompleteOptions((prev) => ({ ...prev, [attribute]: unique }));
|
||||
}, 300);
|
||||
|
||||
const fetchFile = async (tuneId: string, fileName: string) => bufferToFile(await fetchTuneFile(tuneId, fileName), fileName);
|
||||
|
||||
|
@ -603,19 +622,37 @@ const UploadPage = () => {
|
|||
<Row {...rowProps}>
|
||||
<Col span={24} sm={24}>
|
||||
<Item name="vehicleName" rules={requiredTextRules}>
|
||||
<AutoComplete
|
||||
options={autocompleteOptions.vehicleName}
|
||||
onSearch={(search) => searchAutocomplete('vehicleName', search)}
|
||||
backfill
|
||||
>
|
||||
<Input addonBefore="Vehicle name" />
|
||||
</AutoComplete>
|
||||
</Item>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row {...rowProps}>
|
||||
<Col {...colProps}>
|
||||
<Item name="engineMake" rules={requiredTextRules}>
|
||||
<AutoComplete
|
||||
options={autocompleteOptions.engineMake}
|
||||
onSearch={(search) => searchAutocomplete('engineMake', search)}
|
||||
backfill
|
||||
>
|
||||
<Input addonBefore="Engine make" />
|
||||
</AutoComplete>
|
||||
</Item>
|
||||
</Col>
|
||||
<Col {...colProps}>
|
||||
<Item name="engineCode" rules={requiredTextRules}>
|
||||
<AutoComplete
|
||||
options={autocompleteOptions.engineCode}
|
||||
onSearch={(search) => searchAutocomplete('engineCode', search)}
|
||||
backfill
|
||||
>
|
||||
<Input addonBefore="Engine code" />
|
||||
</AutoComplete>
|
||||
</Item>
|
||||
</Col>
|
||||
</Row>
|
||||
|
@ -650,12 +687,24 @@ const UploadPage = () => {
|
|||
<Row {...rowProps}>
|
||||
<Col {...colProps}>
|
||||
<Item name="fuel">
|
||||
<AutoComplete
|
||||
options={autocompleteOptions.fuel}
|
||||
onSearch={(search) => searchAutocomplete('fuel', search)}
|
||||
backfill
|
||||
>
|
||||
<Input addonBefore="Fuel" />
|
||||
</AutoComplete>
|
||||
</Item>
|
||||
</Col>
|
||||
<Col {...colProps}>
|
||||
<Item name="ignition">
|
||||
<AutoComplete
|
||||
options={autocompleteOptions.ignition}
|
||||
onSearch={(search) => searchAutocomplete('ignition', search)}
|
||||
backfill
|
||||
>
|
||||
<Input addonBefore="Ignition" />
|
||||
</AutoComplete>
|
||||
</Item>
|
||||
</Col>
|
||||
</Row>
|
||||
|
|
Loading…
Reference in New Issue