Skip to content

Commit 400f2c1

Browse files
authored
752 Fix excess fetching on /training/slots page (#869)
* Clean up * Fix rule details * Test * Clean up * Revert unrelated changes * PoC dedup * Fix code duplication
1 parent d49f0e1 commit 400f2c1

File tree

7 files changed

+118
-194
lines changed

7 files changed

+118
-194
lines changed

DSL/Ruuter.private/GET/rasa/slots-list.yml

Lines changed: 0 additions & 36 deletions
This file was deleted.

DSL/Ruuter.private/GET/rasa/slots.yml

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,33 +6,31 @@ declaration:
66
accepts: json
77
returns: json
88
namespace: training
9+
params:
10+
- field: filter
11+
type: string
12+
description: "Query string"
13+
- field: from
14+
type: string
15+
description: "Item number"
16+
- field: size
17+
type: string
18+
description: "Page size"
919

1020
getSlots:
1121
call: http.post
1222
args:
13-
url: "[#TRAINING_OPENSEARCH]/domain/_search?pretty=true"
23+
url: "[#TRAINING_OPENSEARCH]/domain/_search/template"
1424
body:
15-
query:
16-
match:
17-
_id: 'slots'
25+
id: "domain-objects-with-pagination"
26+
params:
27+
type: "slots"
28+
filter: ${incoming.params.filter}
29+
from: ${incoming.params.from}
30+
size: ${incoming.params.size}
1831
result: getSlotsResult
1932

20-
mapSlotsData:
21-
call: http.post
22-
args:
23-
url: "[#TRAINING_DMAPPER]/hbs/training/extract_slot_keys"
24-
headers:
25-
type: 'json'
26-
body:
27-
hits: ${getSlotsResult.response.body.hits.hits}
28-
result: slotsData
29-
next: returnSuccess
30-
3133
returnSuccess:
32-
return: ${slotsData.response.body.slots}
34+
return: ${getSlotsResult.response.body.hits.hits[0].fields.filtered_items[0]}
3335
wrapper: false
3436
next: end
35-
36-
returnUnauthorized:
37-
return: "error: unauthorized"
38-
next: end

GUI/src/hooks/useGetColumns.tsx

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { createColumnHelper } from '@tanstack/react-table';
2+
import { MdOutlineModeEditOutline, MdDeleteOutline } from 'react-icons/md';
3+
import { useNavigate } from 'react-router-dom';
4+
import i18n from '../../i18n';
5+
import { Button, Icon } from 'components';
6+
import { useMemo } from 'react';
7+
8+
export const useGetColumns = (type: 'slots' | 'forms', onDeleteItem: (id: string) => void) => {
9+
const navigate = useNavigate();
10+
11+
const cols = useMemo(() => {
12+
const columnHelper = createColumnHelper<string>();
13+
14+
return [
15+
columnHelper.accessor((row) => row, {
16+
header: i18n.t(`training.${type}.titleOne`) || '',
17+
}),
18+
columnHelper.display({
19+
header: '',
20+
cell: (props) => (
21+
<Button appearance="text" onClick={() => navigate(`/training/${type}/${props.row.original}`)}>
22+
<Icon label={i18n.t('global.edit')} icon={<MdOutlineModeEditOutline color={'rgba(0,0,0,0.54)'} />} />
23+
{i18n.t('global.edit')}
24+
</Button>
25+
),
26+
id: 'edit',
27+
meta: {
28+
size: '1%',
29+
},
30+
}),
31+
columnHelper.display({
32+
header: '',
33+
cell: (props) => (
34+
<Button appearance="text" onClick={() => onDeleteItem(props.row.original)}>
35+
<Icon label={i18n.t('global.delete')} icon={<MdDeleteOutline color={'rgba(0,0,0,0.54)'} />} />
36+
{i18n.t('global.delete')}
37+
</Button>
38+
),
39+
id: 'delete',
40+
meta: {
41+
size: '1%',
42+
},
43+
}),
44+
];
45+
}, [navigate, onDeleteItem, type]);
46+
47+
return cols;
48+
};

GUI/src/pages/Training/Forms/index.tsx

Lines changed: 4 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,17 @@
11
import { FC, useMemo, useState } from 'react';
22
import { useTranslation } from 'react-i18next';
3-
import { NavigateFunction, useNavigate } from 'react-router-dom';
3+
import { useNavigate } from 'react-router-dom';
44
import { AxiosError } from 'axios';
55
import { useMutation, useQueryClient } from '@tanstack/react-query';
6-
import { createColumnHelper } from '@tanstack/react-table';
7-
import { MdDeleteOutline, MdOutlineModeEditOutline } from 'react-icons/md';
86

9-
import { Button, Card, DataTable, Dialog, FormInput, Icon, Track } from 'components';
7+
import { Button, Card, DataTable, Dialog, FormInput, Track } from 'components';
108
import { useToast } from 'hooks/useToast';
119
import { deleteForm, getForms } from 'services/forms';
12-
import i18n from '../../../../i18n';
1310
import withAuthorization, { ROLES } from 'hoc/with-authorization';
1411
import { useInfinitePagination } from 'hooks/useInfinitePagination';
1512
import { flattenPaginatedData } from 'utils/api-utils';
1613
import { useDebouncedFilter } from 'hooks/useDebouncedFilter';
14+
import { useGetColumns } from 'hooks/useGetColumns';
1715

1816
const Forms: FC = () => {
1917
const { t } = useTranslation();
@@ -59,7 +57,7 @@ const Forms: FC = () => {
5957
return error.message;
6058
};
6159

62-
const formsColumns = useMemo(() => getColumns(navigate, setDeletableForm), []);
60+
const formsColumns = useGetColumns('forms', setDeletableForm);
6361

6462
if (!forms) return <>Loading...</>;
6563

@@ -106,42 +104,6 @@ const Forms: FC = () => {
106104
);
107105
};
108106

109-
const getColumns = (navigate: NavigateFunction, setDeletableForm: (id: string) => void) => {
110-
const columnHelper = createColumnHelper<string>();
111-
112-
return [
113-
columnHelper.accessor((row) => row, {
114-
header: i18n.t('training.forms.titleOne') || '',
115-
}),
116-
columnHelper.display({
117-
header: '',
118-
cell: (props) => (
119-
<Button appearance="text" onClick={() => navigate(`/training/forms/${props.row.original}`)}>
120-
<Icon label={i18n.t('global.edit')} icon={<MdOutlineModeEditOutline color={'rgba(0,0,0,0.54)'} />} />
121-
{i18n.t('global.edit')}
122-
</Button>
123-
),
124-
id: 'edit',
125-
meta: {
126-
size: '1%',
127-
},
128-
}),
129-
columnHelper.display({
130-
header: '',
131-
cell: (props) => (
132-
<Button appearance="text" onClick={() => setDeletableForm(props.row.original)}>
133-
<Icon label={i18n.t('global.delete')} icon={<MdDeleteOutline color={'rgba(0,0,0,0.54)'} />} />
134-
{i18n.t('global.delete')}
135-
</Button>
136-
),
137-
id: 'delete',
138-
meta: {
139-
size: '1%',
140-
},
141-
}),
142-
];
143-
};
144-
145107
export default withAuthorization(Forms, [
146108
ROLES.ROLE_ADMINISTRATOR,
147109
ROLES.ROLE_CHATBOT_TRAINER,

GUI/src/pages/Training/Rules/ConditionNode.tsx

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
import { FC, useEffect, useMemo } from 'react';
22
import { useTranslation } from 'react-i18next';
3-
import { useQuery } from '@tanstack/react-query';
43
import { Controller, useFieldArray, useForm } from 'react-hook-form';
54
import { Button, FormInput, FormSelect, Icon, Track } from 'components';
65
import { MdOutlineDelete } from 'react-icons/md';
7-
import { Slot } from '../../../types/slot';
86
import { useInfinitePagination } from 'hooks/useInfinitePagination';
97
import { getForms } from 'services/forms';
108
import { flattenPaginatedData } from 'utils/api-utils';
9+
import { getSlots } from 'services/slots';
1110

1211
type NodeDataProps = {
1312
data: {
@@ -46,9 +45,13 @@ const ConditionNode: FC<NodeDataProps> = ({ data }) => {
4645
});
4746
const forms = useMemo(() => flattenPaginatedData(formsData), [formsData]);
4847

49-
const { data: slots } = useQuery<Slot[]>({
48+
const { data: slotsData } = useInfinitePagination<string>({
5049
queryKey: ['slots'],
50+
fetchFn: getSlots,
51+
pageSize: 1000,
5152
});
53+
const slots = useMemo(() => flattenPaginatedData(slotsData), [slotsData]);
54+
5255
const { control, watch } = useForm<Conditions>({
5356
defaultValues: {
5457
conditions: [{ active_loop: { label: '', value: '' } }, { slot: { label: '', value: '' }, value: '' }],
@@ -123,12 +126,9 @@ const ConditionNode: FC<NodeDataProps> = ({ data }) => {
123126
onSelectionChange={(selection) => {
124127
field.onChange(selection);
125128
}}
126-
value={field.value?.label ?? null}
129+
value={field.value?.label}
127130
label={t('training.slot')}
128-
options={Array.from(new Set(slots || [])).map((f) => ({
129-
label: f.id,
130-
value: String(f.id),
131-
}))}
131+
options={slots.map((f) => ({ label: f, value: f }))}
132132
/>
133133
)}
134134
/>
@@ -151,10 +151,10 @@ const ConditionNode: FC<NodeDataProps> = ({ data }) => {
151151
</>
152152
))}
153153
<Track gap={8}>
154-
<Button appearance="success" size="s" onClick={() => append({ active_loop: '' })}>
154+
<Button appearance="success" size="s" onClick={() => append({ active_loop: { label: '', value: '' } })}>
155155
{t('global.add')} active_loop
156156
</Button>
157-
<Button appearance="success" size="s" onClick={() => append({ slot: '', value: '' })}>
157+
<Button appearance="success" size="s" onClick={() => append({ slot: { label: '', value: '' } })}>
158158
{t('global.add')} slot
159159
</Button>
160160
</Track>

0 commit comments

Comments
 (0)