Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Adding a Loading state to buttons #2630

Merged
merged 35 commits into from
Oct 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
b4a9a55
feat: add useThrottle
Silence-dream Sep 27, 2022
2d69cdb
feat: submit button adds the throttling
Silence-dream Sep 28, 2022
420861e
feat(route): add publish and offline button loading
Silence-dream Sep 28, 2022
59ebb8e
feat: hook submit loading
Silence-dream Sep 29, 2022
73233ed
feat: add delete button loading
Silence-dream Sep 29, 2022
4d99636
docs: add license
Silence-dream Sep 29, 2022
9d86b19
Merge branch 'master' into feat-loading-state
Silence-dream Oct 4, 2022
10f4af0
Merge branch 'feat-loading-state' of github.com:Silence-dream/apisix-…
Silence-dream Oct 4, 2022
2a40b32
test(route): correct the test sequence
Silence-dream Oct 4, 2022
e0e284b
test(route): click on the delay
Silence-dream Oct 5, 2022
15e683d
test(route): add custom redirect delay
Silence-dream Oct 7, 2022
9d4edfe
test(route): increase delay
Silence-dream Oct 8, 2022
95cb478
test(route): increase delay
Silence-dream Oct 8, 2022
c4b2bbf
test(route):remove force
Silence-dream Oct 8, 2022
5925816
test(route): increase delay
Silence-dream Oct 8, 2022
f2d7467
test(route): increase delay
Silence-dream Oct 8, 2022
478e4f0
test(upstream): increase delay
Silence-dream Oct 8, 2022
e4b47b4
test(route): increase delay
Silence-dream Oct 9, 2022
f2e3aa2
test: revert
Silence-dream Oct 10, 2022
4570580
test: increase delay
Silence-dream Oct 10, 2022
c489c23
test: increase delay
Silence-dream Oct 10, 2022
27d3cf9
test: revert
Silence-dream Oct 10, 2022
fd8796e
test: fix can't find dom
Silence-dream Oct 10, 2022
96bc692
test: revert
Silence-dream Oct 11, 2022
997d5e6
test: revert
Silence-dream Oct 11, 2022
61de3c6
test: revert
Silence-dream Oct 11, 2022
d97b68a
Merge branch 'feat-loading-state' of github.com:Silence-dream/apisix-…
Silence-dream Oct 11, 2022
4aa28bf
test: revert
Silence-dream Oct 11, 2022
f8e901b
test: increase delay
Silence-dream Oct 11, 2022
d7e2bf1
test: increase delay
Silence-dream Oct 11, 2022
f1e0ae6
test: add deletion interval
Silence-dream Oct 11, 2022
4b0cb0a
test: revert
Silence-dream Oct 11, 2022
4cfbc70
feat: remove custom hooks and add ahooks
Silence-dream Oct 13, 2022
269ae88
fix: enable manual execution
Silence-dream Oct 13, 2022
1a27211
refactor: rename
Silence-dream Oct 17, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions web/cypress/e2e/route/batch-delete-route.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ context('Create and Batch Deletion Routes', () => {
// config label
cy.contains('Manage').click();

// eslint-disable-next-line @typescript-eslint/no-loop-func
cy.get(selector.drawerBody).within(($drawer) => {
cy.wrap($drawer)
.contains('button', 'Add')
Expand Down Expand Up @@ -115,14 +116,15 @@ context('Create and Batch Deletion Routes', () => {
it('should batch delete the name of the route', function () {
cy.contains('Route').click();
const cases = [
[1, 0, 2], //full match
[1, 0, 2], // full match
[0, 1, 2], // partial match
[0, 1, 2], //none match
[0, 1, 2], // none match
];
const prefix = 'test';
cy.wrap([0, 2, 'x']).each(($n, i) => {
cy.get(selector.nameSearchInput).clear().type(`${prefix}${$n}`);
cy.contains('Search').click();
// eslint-disable-next-line @typescript-eslint/no-shadow
cy.wrap(cases[i]).each(($n) => {
cy.contains(`${prefix}${$n}`).should('not.exist');
});
Expand All @@ -132,14 +134,15 @@ context('Create and Batch Deletion Routes', () => {
it('should batch delete the path of the route', function () {
cy.contains('Route').click();
const cases = [
[1, 0, 2], //full match
[1, 0, 2], // full match
[0, 1, 2], // partial match
[0, 1, 2], //none match
[0, 1, 2], // none match
];
const prefix = '/get';
cy.wrap([0, 2, 'x']).each(($n, i) => {
cy.get(selector.nameSearchInput).clear().type(`${prefix}${$n}`);
cy.contains('Search').click();
// eslint-disable-next-line @typescript-eslint/no-shadow
cy.wrap(cases[i]).each(($n) => {
cy.contains(`${prefix}${$n}`).should('not.exist');
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ context('Create Route with search service name', () => {
it('should delete the route and services', function () {
cy.visit('/');
cy.contains('Route').click();
cy.wait(4000);
cy.get(selector.name).type(`${data.routeName}\n`);
cy.contains(data.routeName).siblings().contains('More').click();
cy.contains('Delete').click();
Expand All @@ -171,7 +172,7 @@ context('Create Route with search service name', () => {
cy.contains(data.serviceName).siblings().contains('Delete').click();
cy.contains('button', 'Confirm').click();
cy.get(selector.notification).should('contain', data.deleteServiceSuccess);

cy.get('.ant-notification-close-icon').click().should('not.exist');
cy.contains(data.serviceName2).siblings().contains('Delete').click();
cy.contains('button', 'Confirm').click();
cy.get(selector.notification).should('contain', data.deleteServiceSuccess);
Expand Down
1 change: 1 addition & 0 deletions web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
"@rjsf/antd": "2.2.0",
"@rjsf/core": "2.2.0",
"@types/js-yaml": "^4.0.0",
"ahooks": "^3.7.1",
"ajv": "^7.0.3",
"ajv-formats": "^1.5.1",
"antd": "^4.4.0",
Expand Down
5 changes: 3 additions & 2 deletions web/src/components/ActionBar/ActionBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ type Props = {
lastStep: number;
onChange: (nextStep: number) => void;
withResultView?: boolean;
loading?: boolean;
};

const style: CSSProperties = {
Expand All @@ -37,7 +38,7 @@ const style: CSSProperties = {
width: '100%',
};

const ActionBar: React.FC<Props> = ({ step, lastStep, onChange, withResultView }) => {
const ActionBar: React.FC<Props> = ({ step, lastStep, onChange, withResultView, loading }) => {
const { formatMessage } = useIntl();

if (step > lastStep && !withResultView) {
Expand All @@ -59,7 +60,7 @@ const ActionBar: React.FC<Props> = ({ step, lastStep, onChange, withResultView }
</Button>
</Col>
<Col>
<Button type="primary" onClick={() => onChange(step + 1)}>
<Button type="primary" onClick={() => onChange(step + 1)} loading={loading}>
{step < lastStep
? formatMessage({ id: 'component.actionbar.button.nextStep' })
: formatMessage({ id: 'component.global.submit' })}
Expand Down
9 changes: 7 additions & 2 deletions web/src/pages/Consumer/Create.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import PluginPage from '@/components/Plugin';
import Step1 from './components/Step1';
import Preview from './components/Preview';
import { fetchItem, create, update } from './service';
import { useRequest } from 'ahooks';

const Page: React.FC = (props) => {
const [step, setStep] = useState(1);
Expand All @@ -43,10 +44,14 @@ const Page: React.FC = (props) => {
}
}, []);

const { runAsync: createConsumers, loading: submitLoading } = useRequest(create, {
manual: true,
});

const onSubmit = () => {
const data = { ...form1.getFieldsValue(), plugins } as ConsumerModule.Entity;
const { username } = (props as any).match.params;
(username ? update(username, data) : create(data))
(username ? update(username, data) : createConsumers(data))
.then(() => {
notification.success({
message: `${
Expand Down Expand Up @@ -103,7 +108,7 @@ const Page: React.FC = (props) => {
{step === 3 && <Preview form1={form1} plugins={plugins} />}
</Card>
</PageContainer>
<ActionBar step={step} lastStep={3} onChange={onStepChange} />
<ActionBar loading={submitLoading} step={step} lastStep={3} onChange={onStepChange} />
</>
);
};
Expand Down
19 changes: 12 additions & 7 deletions web/src/pages/Consumer/List.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const Page: React.FC = () => {
const [id, setId] = useState('');
const [editorMode, setEditorMode] = useState<'create' | 'update'>('create');
const { paginationConfig, savePageList, checkPageList } = usePagination();

const [consumerId, setConsumerId] = useState<string>('');
const columns: ProColumns<ConsumerModule.ResEntity>[] = [
{
title: formatMessage({ id: 'page.consumer.username' }),
Expand Down Expand Up @@ -92,15 +92,20 @@ const Page: React.FC = () => {
okText={formatMessage({ id: 'component.global.confirm' })}
cancelText={formatMessage({ id: 'component.global.cancel' })}
onConfirm={() => {
remove(record.username).then(() => {
notification.success({
message: `${formatMessage({ id: 'component.global.delete.consumer.success' })}`,
setConsumerId(record.id);
remove(record.username)
.then(() => {
notification.success({
message: `${formatMessage({ id: 'component.global.delete.consumer.success' })}`,
});
checkPageList(ref);
})
.finally(() => {
setConsumerId('');
});
checkPageList(ref);
});
}}
>
<Button type="primary" danger>
<Button type="primary" danger loading={record.id === consumerId}>
{formatMessage({ id: 'component.global.delete' })}
</Button>
</Popconfirm>
Expand Down
22 changes: 14 additions & 8 deletions web/src/pages/Plugin/List.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ const Page: React.FC = () => {
const [pluginList, setPluginList] = useState<PluginComponent.Meta[]>([]);
const [name, setName] = useState('');
const { paginationConfig, savePageList, checkPageList } = usePagination();
const [pluginId, setPluginId] = useState<string>('');

useEffect(() => {
fetchPluginList().then(setPluginList);
Expand Down Expand Up @@ -79,19 +80,24 @@ const Page: React.FC = () => {
title={formatMessage({ id: 'component.global.popconfirm.title.delete' })}
onConfirm={() => {
const plugins = omit(initialData, [`${record.name}`]);
createOrUpdate({ plugins }).then(() => {
notification.success({
message: formatMessage({ id: 'page.plugin.delete' }),
setPluginId(record.id);
createOrUpdate({ plugins })
.then(() => {
notification.success({
message: formatMessage({ id: 'page.plugin.delete' }),
});
checkPageList(ref);
setInitialData(plugins);
setName('');
})
.finally(() => {
setPluginId('');
});
checkPageList(ref);
setInitialData(plugins);
setName('');
});
}}
okText={formatMessage({ id: 'component.global.confirm' })}
cancelText={formatMessage({ id: 'component.global.cancel' })}
>
<Button type="primary" danger>
<Button type="primary" danger loading={record.id === pluginId}>
{formatMessage({ id: 'component.global.delete' })}
</Button>
</Popconfirm>
Expand Down
18 changes: 12 additions & 6 deletions web/src/pages/Proto/List.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ const Page: React.FC = () => {
};
const [protoData, setProtoData] = useState<ProtoModule.ProtoData>(emptyProtoData);
const [editMode, setEditMode] = useState<ProtoModule.EditMode>('create');
const [deleteLoading, setDeleteLoading] = useState('');

const refreshTable = () => {
ref.current?.reload();
Expand Down Expand Up @@ -97,15 +98,20 @@ const Page: React.FC = () => {
okText={formatMessage({ id: 'page.proto.list.confirm' })}
cancelText={formatMessage({ id: 'page.proto.list.cancel' })}
onConfirm={() => {
remove(record.id).then(() => {
notification.success({
message: formatMessage({ id: 'page.proto.list.delete.successfully' }),
setDeleteLoading(record.id);
remove(record.id)
.then(() => {
notification.success({
message: formatMessage({ id: 'page.proto.list.delete.successfully' }),
});
checkPageList(ref);
})
.finally(() => {
setDeleteLoading('');
});
checkPageList(ref);
});
}}
>
<Button type="primary" danger>
<Button type="primary" danger loading={record.id === deleteLoading}>
{formatMessage({ id: 'page.proto.list.delete' })}
</Button>
</Popconfirm>
Expand Down
11 changes: 7 additions & 4 deletions web/src/pages/Proto/components/ProtoDrawer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { Input } from 'antd';

import { create, update } from '../../service';
import styles from './index.less';
import { useRequest, useThrottleFn } from 'ahooks';

const ProtoDrawer: React.FC<ProtoModule.ProtoDrawerProps> = ({
protoData,
Expand All @@ -38,11 +39,13 @@ const ProtoDrawer: React.FC<ProtoModule.ProtoDrawerProps> = ({
form.setFieldsValue(protoData);
}, [visible]);

const submit = async () => {
const { runAsync: createProto, loading: submitLoading } = useRequest(create, { manual: true });

const { run: submit } = useThrottleFn(async () => {
await form.validateFields();
const formData: ProtoModule.ProtoData = form.getFieldsValue(true);
if (editMode === 'create') {
create(formData).then(() => {
createProto(formData).then(() => {
notification.success({
message: formatMessage({ id: 'page.proto.drawer.create.successfully' }),
});
Expand All @@ -57,7 +60,7 @@ const ProtoDrawer: React.FC<ProtoModule.ProtoDrawerProps> = ({
setVisible(false);
refreshTable();
}
};
});

return (
<Drawer
Expand All @@ -81,7 +84,7 @@ const ProtoDrawer: React.FC<ProtoModule.ProtoDrawerProps> = ({
{formatMessage({ id: 'component.global.cancel' })}
</Button>
<Space>
<Button type="primary" onClick={() => submit()}>
<Button type="primary" onClick={() => submit()} loading={submitLoading}>
{formatMessage({ id: 'component.global.submit' })}
</Button>
</Space>
Expand Down
19 changes: 13 additions & 6 deletions web/src/pages/Route/Create.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { Card, Steps, Form, Modal } from 'antd';
import { PageHeaderWrapper } from '@ant-design/pro-layout';
import { history, useIntl } from 'umi';
import { isEmpty } from 'lodash';

import { useRequest } from 'ahooks';
import ActionBar from '@/components/ActionBar';
import FlowGraph from '@/components/PluginFlow/components/FlowGraph';

Expand Down Expand Up @@ -226,6 +226,8 @@ const Page: React.FC<Props> = (props) => {
return true;
};

const { runAsync: createRoutes, loading: submitLoading } = useRequest(create, { manual: true });

const onStepChange = (nextStep: number) => {
const onUpdateOrCreate = () => {
const routeData = {
Expand All @@ -234,18 +236,17 @@ const Page: React.FC<Props> = (props) => {
step3Data,
advancedMatchingRules,
} as RouteModule.RequestData;

const { path } = props.route
const { path } = props.route;

if (path.indexOf('edit') !== -1) {
update((props as any).match.params.rid, routeData).then(() => {
setStep(5);
});
} else {
if (path.indexOf('duplicate') !== -1) {
delete routeData.form1Data.id
delete routeData.form1Data.id;
}
create(routeData).then(() => {
createRoutes(routeData).then(() => {
setStep(5);
});
}
Expand Down Expand Up @@ -318,7 +319,13 @@ const Page: React.FC<Props> = (props) => {
{renderStepList()}
</Card>
</PageHeaderWrapper>
<ActionBar step={step} lastStep={redirect ? 2 : 4} onChange={onStepChange} withResultView />
<ActionBar
step={step}
loading={submitLoading}
lastStep={redirect ? 2 : 4}
onChange={onStepChange}
withResultView
/>
</>
);
};
Expand Down
Loading