Skip to content

Commit 8e98e4b

Browse files
authoredFeb 20, 2025··
extend configuration in the myServices table. (#1517)
1 parent 451c252 commit 8e98e4b

18 files changed

+560
-158
lines changed
 

‎src/components/content/deployedServices/myServices/MyServices.tsx

+9-4
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020
RiseOutlined,
2121
SyncOutlined,
2222
} from '@ant-design/icons';
23+
import { useQueryClient } from '@tanstack/react-query';
2324
import {
2425
Button,
2526
Dropdown,
@@ -73,7 +74,8 @@ import { RetryServiceSubmit } from '../../order/retryDeployment/RetryServiceSubm
7374
import useRedeployFailedDeploymentQuery from '../../order/retryDeployment/useRedeployFailedDeploymentQuery';
7475
import { Scale } from '../../order/scale/Scale';
7576
import { CreateServiceActionForm } from '../../order/serviceActions/CreateServiceActionForm';
76-
import { CurrentServiceConfiguration } from '../../order/serviceConfiguration/CurrentServiceConfiguration';
77+
import { ServiceConfiguration } from '../../order/serviceConfiguration/ServiceConfiguration.tsx';
78+
import { getCurrentConfigurationQueryKey } from '../../order/serviceConfiguration/useGetConfigurationOfServiceQuery.ts';
7779
import { ServicePorting } from '../../order/servicePorting/ServicePorting.tsx';
7880
import RestartServiceStatusAlert from '../../order/serviceState/restart/RestartServiceStatusAlert';
7981
import { useServiceStateRestartQuery } from '../../order/serviceState/restart/useServiceStateRestartQuery';
@@ -119,6 +121,7 @@ import useListDeployedServicesDetailsQuery from './query/useListDeployedServices
119121
import { TooltipWhenDetailsDisabled } from './TooltipWhenDetailsDisabled.tsx';
120122

121123
function MyServices(): React.JSX.Element {
124+
const queryClient = useQueryClient();
122125
const navigate = useNavigate();
123126

124127
const location = useLocation();
@@ -1269,6 +1272,7 @@ function MyServices(): React.JSX.Element {
12691272
const handleMyServiceConfigurationModalClose = () => {
12701273
setActiveRecord(undefined);
12711274
setIsMyServiceConfigurationModalOpen(false);
1275+
void queryClient.resetQueries({ queryKey: getCurrentConfigurationQueryKey(activeRecord?.serviceId ?? '') });
12721276
};
12731277

12741278
const handleServiceActionsOpenModal = (record: DeployedService) => {
@@ -1419,12 +1423,13 @@ function MyServices(): React.JSX.Element {
14191423
{activeRecord ? (
14201424
<Modal
14211425
title={'Service Configuration'}
1422-
width={1600}
1426+
width={680}
14231427
footer={null}
14241428
open={isMyServiceConfigurationModalOpen}
1429+
destroyOnClose={true}
14251430
onCancel={handleMyServiceConfigurationModalClose}
14261431
>
1427-
<CurrentServiceConfiguration
1432+
<ServiceConfiguration
14281433
userOrderableServiceVo={getOrderableServiceDetails.data}
14291434
deployedService={activeRecord}
14301435
/>
@@ -1433,7 +1438,7 @@ function MyServices(): React.JSX.Element {
14331438
{activeRecord ? (
14341439
<Modal
14351440
title={'Service Actions'}
1436-
width={1600}
1441+
width={680}
14371442
footer={null}
14381443
open={isServiceActionsModalOpen}
14391444
onCancel={handleServiceActionsModalClose}

‎src/components/content/order/serviceActions/elements/BooleanInput.tsx ‎src/components/content/order/common/formItemElements/BooleanInput.tsx

+4-8
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,10 @@ export function BooleanInput({ actionParameter }: { actionParameter: ServiceChan
1717
key={actionParameter.name}
1818
name={actionParameter.name}
1919
label={
20-
<p
21-
className={`${serviceOrderStyles.orderFormSelectionStyle} ${serviceOrderStyles.orderFormItemName}`}
22-
>
23-
<Tooltip placement='rightTop' title={actionParameter.description}>
24-
{actionParameter.name}&nbsp;
25-
<QuestionCircleOutlined />
26-
</Tooltip>
27-
</p>
20+
<Tooltip placement='rightTop' title={actionParameter.description}>
21+
{actionParameter.name}&nbsp;
22+
<QuestionCircleOutlined />
23+
</Tooltip>
2824
}
2925
rules={[{ type: 'boolean' }, { required: true }]}
3026
valuePropName='checked'

‎src/components/content/order/serviceActions/elements/NumberInput.tsx ‎src/components/content/order/common/formItemElements/NumberInput.tsx

+5-9
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { Rule } from 'rc-field-form/lib/interface';
44
import React from 'react';
55
import serviceOrderStyles from '../../../../../styles/service-order.module.css';
66
import { ServiceChangeParameter } from '../../../../../xpanse-api/generated';
7-
import { DeployVariableSchema } from '../../types/DeployVariableSchema';
7+
import { DeployVariableSchema } from '../../types/DeployVariableSchema.ts';
88

99
export function NumberInput({ actionParameter }: { actionParameter: ServiceChangeParameter }): React.JSX.Element {
1010
const ruleItems: Rule[] = [{ required: true }, { type: 'number' }];
@@ -39,14 +39,10 @@ export function NumberInput({ actionParameter }: { actionParameter: ServiceChang
3939
key={actionParameter.name}
4040
name={actionParameter.name}
4141
label={
42-
<p
43-
className={`${serviceOrderStyles.orderFormSelectionStyle} ${serviceOrderStyles.orderFormItemName}`}
44-
>
45-
<Tooltip placement='rightTop' title={actionParameter.description}>
46-
{actionParameter.name}&nbsp;
47-
<QuestionCircleOutlined />
48-
</Tooltip>
49-
</p>
42+
<Tooltip placement='rightTop' title={actionParameter.description}>
43+
{actionParameter.name}&nbsp;
44+
<QuestionCircleOutlined />
45+
</Tooltip>
5046
}
5147
rules={ruleItems}
5248
initialValue={Number(actionParameter.initialValue)}

‎src/components/content/order/serviceActions/elements/TextInput.tsx ‎src/components/content/order/common/formItemElements/TextInput.tsx

+5-9
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { Rule } from 'rc-field-form/lib/interface';
44
import React from 'react';
55
import serviceOrderStyles from '../../../../../styles/service-order.module.css';
66
import { sensitiveScope, ServiceChangeParameter } from '../../../../../xpanse-api/generated';
7-
import { DeployVariableSchema } from '../../types/DeployVariableSchema';
7+
import { DeployVariableSchema } from '../../types/DeployVariableSchema.ts';
88

99
export function TextInput({ actionParameter }: { actionParameter: ServiceChangeParameter }): React.JSX.Element {
1010
let regExp: RegExp;
@@ -34,14 +34,10 @@ export function TextInput({ actionParameter }: { actionParameter: ServiceChangeP
3434
key={actionParameter.name}
3535
name={actionParameter.name}
3636
label={
37-
<p
38-
className={`${serviceOrderStyles.orderFormSelectionStyle} ${serviceOrderStyles.orderFormItemName}`}
39-
>
40-
<Tooltip placement='rightTop' title={actionParameter.description}>
41-
{actionParameter.name}&nbsp;
42-
<QuestionCircleOutlined />
43-
</Tooltip>
44-
</p>
37+
<Tooltip placement='rightTop' title={actionParameter.description}>
38+
{actionParameter.name}&nbsp;
39+
<QuestionCircleOutlined />
40+
</Tooltip>
4541
}
4642
rules={ruleItems}
4743
initialValue={actionParameter.initialValue}

‎src/components/content/order/orderStatus/OrderProcessingStatus.tsx

+22-1
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ export const OrderProcessingStatus = ({
7676
if (serviceOrderStatus.taskStatus === 'successful') {
7777
return (
7878
<div>
79-
<span>{'Destroyed Successfully'}</span>
79+
<span>{'Destroyed Successfully.'}</span>
8080
</div>
8181
);
8282
} else if (serviceOrderStatus.taskStatus === 'failed') {
@@ -92,5 +92,26 @@ export const OrderProcessingStatus = ({
9292
);
9393
}
9494
}
95+
96+
if (operationType === OperationType.UpdateConfig) {
97+
if (serviceOrderStatus.taskStatus === 'successful') {
98+
return (
99+
<div>
100+
<span>{'Service configuration updated successfully.'}</span>
101+
</div>
102+
);
103+
} else if (serviceOrderStatus.taskStatus === 'failed') {
104+
return (
105+
<div>
106+
<span>{'Service configuration updated failed.'}</span>
107+
<div>
108+
{selectedServiceHostingType === serviceHostingType.SELF
109+
? serviceOrderStatus.error?.details.join()
110+
: errorMsg}
111+
</div>
112+
</div>
113+
);
114+
}
115+
}
95116
return <></>;
96117
};

‎src/components/content/order/serviceActions/ServiceActionParameterItem.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import React from 'react';
22
import { ServiceChangeParameter } from '../../../../xpanse-api/generated';
3-
import { BooleanInput } from './elements/BooleanInput';
4-
import { NumberInput } from './elements/NumberInput';
5-
import { TextInput } from './elements/TextInput';
3+
import { BooleanInput } from '../common/formItemElements/BooleanInput.tsx';
4+
import { NumberInput } from '../common/formItemElements/NumberInput.tsx';
5+
import { TextInput } from '../common/formItemElements/TextInput.tsx';
66

77
export function ServiceActionParameterItem({
88
actionParameter,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
* SPDX-FileCopyrightText: Huawei Inc.
4+
*/
5+
6+
import { CheckOutlined, CopyOutlined } from '@ant-design/icons';
7+
import { Typography } from 'antd';
8+
import React from 'react';
9+
import { v4 as uuidv4 } from 'uuid';
10+
import submitResultStyles from '../../../../styles/submit-result.module.css';
11+
12+
function ConfigSubmitResultDetails({
13+
msg,
14+
orderId,
15+
}: {
16+
msg: string | React.JSX.Element;
17+
orderId: string;
18+
}): React.JSX.Element {
19+
const { Paragraph } = Typography;
20+
return (
21+
<div>
22+
<div className={submitResultStyles.resultContainer}>
23+
Order ID:&nbsp;
24+
<Paragraph
25+
className={submitResultStyles.resultMainDetails}
26+
copyable={{
27+
text: String(orderId),
28+
icon: [
29+
<CopyOutlined className={submitResultStyles.showDetailsTypographyCopy} key={uuidv4()} />,
30+
<CheckOutlined className={submitResultStyles.showDetailsTypographyCopy} key={uuidv4()} />,
31+
],
32+
}}
33+
>
34+
<span className={submitResultStyles.showDetailsTypographyCopyInfo}>{orderId}</span>
35+
</Paragraph>
36+
</div>
37+
{msg}
38+
</div>
39+
);
40+
}
41+
42+
export default ConfigSubmitResultDetails;

‎src/components/content/order/serviceConfiguration/CurrentServiceConfiguration.tsx

-43
This file was deleted.

‎src/components/content/order/serviceConfiguration/CurrentServiceConfigurationDetails.tsx

-81
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
* SPDX-FileCopyrightText: Huawei Inc.
4+
*/
5+
6+
import React from 'react';
7+
import { ServiceChangeParameter } from '../../../../xpanse-api/generated';
8+
import { BooleanInput } from '../common/formItemElements/BooleanInput.tsx';
9+
import { NumberInput } from '../common/formItemElements/NumberInput.tsx';
10+
import { TextInput } from '../common/formItemElements/TextInput.tsx';
11+
12+
export function ServiceConfigParameterItem({
13+
configParameter,
14+
}: {
15+
configParameter: ServiceChangeParameter | undefined;
16+
}): React.JSX.Element {
17+
if (!configParameter) {
18+
return <></>;
19+
}
20+
switch (configParameter.dataType) {
21+
case 'string':
22+
return <TextInput actionParameter={configParameter} />;
23+
case 'number':
24+
return <NumberInput actionParameter={configParameter} />;
25+
case 'boolean':
26+
return <BooleanInput actionParameter={configParameter} />;
27+
default:
28+
return <></>;
29+
}
30+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
* SPDX-FileCopyrightText: Huawei Inc.
4+
*/
5+
6+
import { UseMutationResult, UseQueryResult } from '@tanstack/react-query';
7+
import React, { useMemo } from 'react';
8+
import {
9+
ChangeServiceConfigurationData,
10+
ErrorResponse,
11+
serviceHostingType,
12+
ServiceOrder,
13+
ServiceOrderStatusUpdate,
14+
taskStatus,
15+
} from '../../../../xpanse-api/generated';
16+
import { convertStringArrayToUnorderedList } from '../../../utils/generateUnorderedList';
17+
import { isHandleKnownErrorResponse } from '../../common/error/isHandleKnownErrorResponse.ts';
18+
import { OrderProcessingStatus } from '../orderStatus/OrderProcessingStatus.tsx';
19+
import { OperationType } from '../types/OperationType';
20+
import { UpdateConfigResult } from './UpdateConfigResult.tsx';
21+
22+
function ServiceConfigStatusAlert({
23+
serviceId,
24+
serviceHostType,
25+
updateConfigRequest,
26+
getUpdateConfigStatusPollingQuery,
27+
}: {
28+
serviceId: string;
29+
serviceHostType: serviceHostingType;
30+
updateConfigRequest: UseMutationResult<ServiceOrder, Error, ChangeServiceConfigurationData>;
31+
getUpdateConfigStatusPollingQuery: UseQueryResult<ServiceOrderStatusUpdate>;
32+
}): React.JSX.Element {
33+
const msg = useMemo(() => {
34+
if (updateConfigRequest.isPending) {
35+
return 'Request submission in-progress';
36+
} else if (updateConfigRequest.isError) {
37+
if (isHandleKnownErrorResponse(updateConfigRequest.error)) {
38+
const response: ErrorResponse = updateConfigRequest.error.body;
39+
return getOrderSubmissionFailedDisplay(response.errorType, response.details);
40+
} else {
41+
return getOrderSubmissionFailedDisplay(updateConfigRequest.error.name, [
42+
updateConfigRequest.error.message,
43+
]);
44+
}
45+
} else if (updateConfigRequest.isSuccess) {
46+
if (
47+
getUpdateConfigStatusPollingQuery.isSuccess &&
48+
(getUpdateConfigStatusPollingQuery.data.taskStatus.toString() === taskStatus.SUCCESSFUL.toString() ||
49+
getUpdateConfigStatusPollingQuery.data.taskStatus.toString() === taskStatus.FAILED.toString())
50+
) {
51+
return (
52+
<OrderProcessingStatus
53+
operationType={OperationType.UpdateConfig}
54+
serviceOrderStatus={getUpdateConfigStatusPollingQuery.data}
55+
serviceId={serviceId}
56+
selectedServiceHostingType={serviceHostType}
57+
/>
58+
);
59+
} else if (getUpdateConfigStatusPollingQuery.isError) {
60+
if (serviceHostType === serviceHostingType.SERVICE_VENDOR) {
61+
return 'Status polling failed. Please visit MyServices page to check the status of the request and contact service vendor for error details.';
62+
} else {
63+
return 'Status polling failed. Please visit MyServices page to check the status of the request';
64+
}
65+
} else if (
66+
getUpdateConfigStatusPollingQuery.isPending ||
67+
!getUpdateConfigStatusPollingQuery.data.isOrderCompleted
68+
) {
69+
return 'Updating, Please wait...';
70+
}
71+
}
72+
}, [
73+
updateConfigRequest.isPending,
74+
updateConfigRequest.isError,
75+
updateConfigRequest.isSuccess,
76+
updateConfigRequest.error,
77+
getUpdateConfigStatusPollingQuery.isSuccess,
78+
getUpdateConfigStatusPollingQuery.data,
79+
getUpdateConfigStatusPollingQuery.isError,
80+
getUpdateConfigStatusPollingQuery.isPending,
81+
serviceId,
82+
serviceHostType,
83+
]);
84+
85+
const alertType = useMemo(() => {
86+
if (updateConfigRequest.isPending) {
87+
return 'success';
88+
} else if (updateConfigRequest.isError || getUpdateConfigStatusPollingQuery.isError) {
89+
return 'error';
90+
} else if (updateConfigRequest.isSuccess) {
91+
if (
92+
getUpdateConfigStatusPollingQuery.isSuccess &&
93+
getUpdateConfigStatusPollingQuery.data.taskStatus.toString() === taskStatus.FAILED.toString()
94+
) {
95+
return 'error';
96+
} else if (
97+
getUpdateConfigStatusPollingQuery.isSuccess &&
98+
getUpdateConfigStatusPollingQuery.data.taskStatus.toString() === taskStatus.SUCCESSFUL.toString()
99+
) {
100+
return 'success';
101+
} else if (
102+
getUpdateConfigStatusPollingQuery.isPending ||
103+
getUpdateConfigStatusPollingQuery.data.taskStatus.toString() === taskStatus.IN_PROGRESS.toString()
104+
) {
105+
return 'success';
106+
}
107+
}
108+
return 'success';
109+
}, [updateConfigRequest, getUpdateConfigStatusPollingQuery]);
110+
111+
function getOrderSubmissionFailedDisplay(errorType: string, reasons: string[]) {
112+
return (
113+
<div>
114+
<span>{errorType.length > 0 ? errorType : 'Service config request failed.'}</span>
115+
<div>{convertStringArrayToUnorderedList(reasons)}</div>
116+
</div>
117+
);
118+
}
119+
120+
const getOrderId = (): string => {
121+
if (updateConfigRequest.isSuccess) {
122+
return updateConfigRequest.data.orderId;
123+
} else {
124+
if (isHandleKnownErrorResponse(updateConfigRequest.error) && 'orderId' in updateConfigRequest.error.body) {
125+
return updateConfigRequest.error.body.orderId as string;
126+
} else {
127+
return '';
128+
}
129+
}
130+
};
131+
132+
return <UpdateConfigResult msg={msg ?? ''} orderId={getOrderId()} type={alertType} />;
133+
}
134+
135+
export default ServiceConfigStatusAlert;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
* SPDX-FileCopyrightText: Huawei Inc.
4+
*/
5+
6+
import React from 'react';
7+
import '../../../../styles/app.module.css';
8+
import {
9+
DeployedServiceDetails,
10+
UserOrderableServiceVo,
11+
VendorHostedDeployedServiceDetails,
12+
} from '../../../../xpanse-api/generated';
13+
import { ServiceConfigurationDetails } from './ServiceConfigurationDetails.tsx';
14+
15+
export const ServiceConfiguration = ({
16+
userOrderableServiceVo,
17+
deployedService,
18+
}: {
19+
userOrderableServiceVo: UserOrderableServiceVo | undefined;
20+
deployedService: DeployedServiceDetails | VendorHostedDeployedServiceDetails;
21+
}): React.JSX.Element => {
22+
return (
23+
<div>
24+
<ServiceConfigurationDetails
25+
userOrderableServiceVo={userOrderableServiceVo}
26+
deployedService={deployedService}
27+
/>
28+
</div>
29+
);
30+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
* SPDX-FileCopyrightText: Huawei Inc.
4+
*/
5+
6+
import { CheckCircleOutlined, CloseCircleOutlined, EditOutlined } from '@ant-design/icons';
7+
import { Button, Empty, Form, Input, Popconfirm, Row, Skeleton } from 'antd';
8+
import React, { useState } from 'react';
9+
import '../../../../styles/app.module.css';
10+
import serviceOrderStyles from '../../../../styles/service-order.module.css';
11+
import {
12+
type ChangeServiceConfigurationData,
13+
DeployedServiceDetails,
14+
ServiceConfigurationUpdate,
15+
serviceHostingType,
16+
taskStatus,
17+
UserOrderableServiceVo,
18+
VendorHostedDeployedServiceDetails,
19+
} from '../../../../xpanse-api/generated';
20+
import { useLatestServiceOrderStatusQuery } from '../../common/queries/useLatestServiceOrderStatusQuery.ts';
21+
import { ServiceConfigParameterItem } from './ServiceConfigParameterItem.tsx';
22+
import ServiceConfigStatusAlert from './ServiceConfigStatusAlert.tsx';
23+
import useGetCurrentConfigurationOfServiceQuery from './useGetConfigurationOfServiceQuery.ts';
24+
import { useUpdateServiceConfigurationRequest } from './useUpdateServiceConfigurationRequest.ts';
25+
26+
export const ServiceConfigurationDetails = ({
27+
userOrderableServiceVo,
28+
deployedService,
29+
}: {
30+
deployedService: DeployedServiceDetails | VendorHostedDeployedServiceDetails;
31+
userOrderableServiceVo: UserOrderableServiceVo | undefined;
32+
}): React.JSX.Element => {
33+
const [form] = Form.useForm();
34+
const [isUpdateConfig, setIsUpdateConfig] = useState<boolean>(false);
35+
const [isShowUpdateConfigResult, setIsShowUpdateConfigResult] = useState<boolean>(false);
36+
37+
const getCurrentConfigurationOfServiceQuery = useGetCurrentConfigurationOfServiceQuery(deployedService.serviceId);
38+
39+
const updateConfigRequest = useUpdateServiceConfigurationRequest();
40+
41+
const getUpdateConfigStatusPollingQuery = useLatestServiceOrderStatusQuery(
42+
updateConfigRequest.data?.orderId ?? '',
43+
updateConfigRequest.isSuccess,
44+
[taskStatus.SUCCESSFUL, taskStatus.FAILED]
45+
);
46+
47+
const updateConfig = (values: ServiceConfigurationUpdate) => {
48+
setIsShowUpdateConfigResult(true);
49+
const data: ChangeServiceConfigurationData = {
50+
requestBody: { configuration: values },
51+
serviceId: deployedService.serviceId,
52+
};
53+
updateConfigRequest.mutate(data);
54+
};
55+
56+
const initialValues = React.useMemo(() => {
57+
const config = getCurrentConfigurationOfServiceQuery.data?.configuration ?? {};
58+
const numericKeys =
59+
userOrderableServiceVo?.configurationParameters
60+
?.filter((param) => param.dataType === 'number')
61+
.map((param) => param.name) ?? [];
62+
63+
const numericConfig = Object.keys(config).reduce<Record<string, unknown>>((acc, key) => {
64+
if (numericKeys.includes(key)) {
65+
acc[key] = Number(config[key]) || 0;
66+
} else {
67+
acc[key] = config[key];
68+
}
69+
return acc;
70+
}, {});
71+
72+
return {
73+
...numericConfig,
74+
updatedTime: getCurrentConfigurationOfServiceQuery.data?.updatedTime,
75+
};
76+
}, [getCurrentConfigurationOfServiceQuery.data, userOrderableServiceVo]);
77+
78+
if (getCurrentConfigurationOfServiceQuery.isLoading || getCurrentConfigurationOfServiceQuery.isPending) {
79+
return <Skeleton active />;
80+
}
81+
82+
if (!userOrderableServiceVo || !getCurrentConfigurationOfServiceQuery.data) {
83+
return <Empty />;
84+
}
85+
86+
return (
87+
<>
88+
<div className={serviceOrderStyles.serviceConfigContainer}>
89+
{isShowUpdateConfigResult ? (
90+
<ServiceConfigStatusAlert
91+
key={deployedService.serviceId}
92+
serviceId={deployedService.serviceId}
93+
serviceHostType={deployedService.serviceHostingType as serviceHostingType}
94+
updateConfigRequest={updateConfigRequest}
95+
getUpdateConfigStatusPollingQuery={getUpdateConfigStatusPollingQuery}
96+
/>
97+
) : null}
98+
<Form
99+
form={form}
100+
key={'serviceConfiguration'}
101+
layout='vertical'
102+
disabled={!isUpdateConfig}
103+
className={serviceOrderStyles.orderFormInlineDisplay}
104+
initialValues={initialValues}
105+
>
106+
<div className={serviceOrderStyles.orderParamItemRow}>
107+
<div className={serviceOrderStyles.orderParamItemContent}>
108+
<Form.Item
109+
key={getCurrentConfigurationOfServiceQuery.data.updatedTime}
110+
label={'config last updated at:'}
111+
initialValue={getCurrentConfigurationOfServiceQuery.data.updatedTime}
112+
>
113+
<Input value={getCurrentConfigurationOfServiceQuery.data.updatedTime} disabled={true} />
114+
</Form.Item>
115+
</div>
116+
</div>
117+
{getCurrentConfigurationOfServiceQuery.data.configuration ? (
118+
Object.entries(getCurrentConfigurationOfServiceQuery.data.configuration).map(([key]) => (
119+
<div key={key}>
120+
<ServiceConfigParameterItem
121+
configParameter={userOrderableServiceVo.configurationParameters?.find(
122+
(param) => param.name === key
123+
)}
124+
/>
125+
</div>
126+
))
127+
) : (
128+
<></>
129+
)}
130+
<Row justify='space-around'>
131+
<div className={serviceOrderStyles.serviceConfigUpdate}>
132+
<>
133+
<Button
134+
type='primary'
135+
onClick={() => {
136+
setIsUpdateConfig(true);
137+
}}
138+
disabled={
139+
isUpdateConfig ||
140+
updateConfigRequest.isPending ||
141+
updateConfigRequest.isSuccess ||
142+
getUpdateConfigStatusPollingQuery.isSuccess
143+
}
144+
>
145+
<EditOutlined /> Update
146+
</Button>
147+
&nbsp;&nbsp;&nbsp;
148+
<Popconfirm
149+
title='Update current config'
150+
description='Are you sure to update current config?'
151+
cancelText='Yes'
152+
okText='No'
153+
onCancel={() => {
154+
form.validateFields()
155+
.then((values: ServiceConfigurationUpdate) => {
156+
updateConfig(values);
157+
setIsUpdateConfig(false);
158+
})
159+
.catch((errorInfo: unknown) => {
160+
return errorInfo;
161+
});
162+
}}
163+
>
164+
<Button type='primary' htmlType='submit' disabled={!isUpdateConfig}>
165+
<CheckCircleOutlined /> Submit
166+
</Button>
167+
</Popconfirm>
168+
&nbsp;&nbsp;&nbsp;
169+
<Button
170+
type='primary'
171+
onClick={() => {
172+
form.resetFields();
173+
setIsUpdateConfig(false);
174+
}}
175+
disabled={!isUpdateConfig}
176+
>
177+
<CloseCircleOutlined /> Cancel
178+
</Button>
179+
</>
180+
</div>
181+
</Row>
182+
</Form>
183+
</div>
184+
</>
185+
);
186+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
* SPDX-FileCopyrightText: Huawei Inc.
4+
*/
5+
6+
import { Alert } from 'antd';
7+
8+
import React from 'react';
9+
import submitAlertStyles from '../../../../styles/submit-alert.module.css';
10+
import ConfigSubmitResultDetails from './ConfigSubmitResultDetails.tsx';
11+
12+
export const UpdateConfigResult = ({
13+
msg,
14+
orderId,
15+
type,
16+
}: {
17+
msg: string | React.JSX.Element;
18+
orderId: string;
19+
type: 'success' | 'error';
20+
}): React.JSX.Element => {
21+
return (
22+
<div className={submitAlertStyles.submitAlertTip}>
23+
{' '}
24+
<Alert
25+
message={`Processing Status`}
26+
description={<ConfigSubmitResultDetails msg={msg} orderId={orderId} />}
27+
showIcon
28+
closable={true}
29+
type={type}
30+
/>{' '}
31+
</div>
32+
);
33+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
* SPDX-FileCopyrightText: Huawei Inc.
4+
*/
5+
6+
import { useQuery } from '@tanstack/react-query';
7+
import {
8+
getCurrentConfigurationOfService,
9+
type GetCurrentConfigurationOfServiceData,
10+
} from '../../../../xpanse-api/generated';
11+
12+
export default function useGetCurrentConfigurationOfServiceQuery(serviceId: string) {
13+
return useQuery({
14+
queryKey: getCurrentConfigurationQueryKey(serviceId),
15+
queryFn: () => {
16+
const data: GetCurrentConfigurationOfServiceData = {
17+
serviceId: serviceId,
18+
};
19+
return getCurrentConfigurationOfService(data);
20+
},
21+
refetchOnWindowFocus: false,
22+
});
23+
}
24+
25+
export function getCurrentConfigurationQueryKey(serviceId: string): string[] {
26+
return ['getCurrentConfigurationOfService', serviceId];
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
* SPDX-FileCopyrightText: Huawei Inc.
4+
*/
5+
6+
import { useMutation } from '@tanstack/react-query';
7+
import { changeServiceConfiguration, type ChangeServiceConfigurationData } from '../../../../xpanse-api/generated';
8+
9+
const updateCurrentServiceConfigurationKey: string = 'updateCurrentServiceConfig';
10+
11+
export function useUpdateServiceConfigurationRequest() {
12+
return useMutation({
13+
mutationKey: [updateCurrentServiceConfigurationKey],
14+
mutationFn: (data: ChangeServiceConfigurationData) => {
15+
return changeServiceConfiguration(data);
16+
},
17+
gcTime: 0,
18+
});
19+
}

‎src/components/content/order/types/OperationType.ts

+1
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@ export enum OperationType {
99
Modify,
1010
Recreate,
1111
Port,
12+
UpdateConfig,
1213
}

‎src/styles/service-order.module.css

+9
Original file line numberDiff line numberDiff line change
@@ -574,3 +574,12 @@
574574
.service-order-api-doc-custom-button:hover {
575575
background-color: transparent !important;
576576
}
577+
578+
.service-config-container {
579+
padding: 8px;
580+
display: grid;
581+
}
582+
583+
.service-config-update {
584+
text-align: left;
585+
}

0 commit comments

Comments
 (0)
Please sign in to comment.