mirror of
https://github.com/kubevela/kubevela.git
synced 2026-08-19 04:26:39 +00:00
1.add application list page (#779)
2.ignore the deleted applicationconfig resource instead return nil 3.code style fix
This commit is contained in:
@@ -3,6 +3,12 @@
|
||||
path: '/',
|
||||
redirect: `/System`,
|
||||
},
|
||||
{
|
||||
name: 'applications',
|
||||
icon: 'appstore',
|
||||
path: `/applications`,
|
||||
component: './Application',
|
||||
},
|
||||
{
|
||||
name: 'system',
|
||||
icon: 'setting',
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import React from 'react';
|
||||
|
||||
import { Menu, message, Spin, Typography } from 'antd';
|
||||
import classNames from 'classnames';
|
||||
import { useModel } from 'umi';
|
||||
|
||||
import { DownOutlined } from '@ant-design/icons';
|
||||
|
||||
@@ -2,4 +2,5 @@ export default {
|
||||
'menu.home': 'Home',
|
||||
'menu.system': 'System',
|
||||
'menu.system.environment': 'Environment',
|
||||
'menu.applications': 'Applications',
|
||||
};
|
||||
|
||||
@@ -2,4 +2,5 @@ export default {
|
||||
'menu.home': '首页',
|
||||
'menu.system': '系统',
|
||||
'menu.system.environment': '环境',
|
||||
'menu.applications': '应用列表',
|
||||
};
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
import React, { useCallback } from 'react';
|
||||
|
||||
import { Button, Card, message, Popconfirm, Space, Table } from 'antd';
|
||||
import { Link, useModel, useRequest } from 'umi';
|
||||
|
||||
import { deleteApplication, getApplications } from '@/services/application';
|
||||
import compatibleDayjs from '@/utils/compatibleDayjs';
|
||||
import { PlusOutlined } from '@ant-design/icons';
|
||||
import { PageContainer } from '@ant-design/pro-layout';
|
||||
|
||||
export default () => {
|
||||
const { currentEnvironment } = useModel('useEnvironmentModel');
|
||||
const { data, loading, run: loadApps } = useRequest(
|
||||
async () => {
|
||||
if (currentEnvironment?.envName == null) {
|
||||
return { code: 200, data: [] } as API.VelaResponse<Array<API.Application>>;
|
||||
}
|
||||
return getApplications(currentEnvironment.envName);
|
||||
},
|
||||
{
|
||||
refreshDeps: [currentEnvironment],
|
||||
},
|
||||
);
|
||||
|
||||
// delete application
|
||||
const remove = useCallback(
|
||||
async (appName: string) => {
|
||||
const envName = currentEnvironment?.envName;
|
||||
if (envName == null) {
|
||||
throw new Error('Unable to determine the current environment name.');
|
||||
}
|
||||
|
||||
const response = await deleteApplication(envName, appName);
|
||||
loadApps();
|
||||
return response;
|
||||
},
|
||||
[currentEnvironment],
|
||||
);
|
||||
|
||||
return (
|
||||
<PageContainer>
|
||||
<Card>
|
||||
<div style={{ marginBottom: '10px' }}>
|
||||
<Space>
|
||||
<Button type="primary" icon={<PlusOutlined />}>
|
||||
Create
|
||||
</Button>
|
||||
</Space>
|
||||
</div>
|
||||
<Table
|
||||
dataSource={data ?? []}
|
||||
rowKey={(record) => record.name}
|
||||
loading={loading ? { delay: 300 } : undefined}
|
||||
columns={[
|
||||
{
|
||||
title: 'Name',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
render: (text, record) => {
|
||||
return (
|
||||
<Link
|
||||
to={{
|
||||
pathname: `${window.routerBase}applications/${record.name}`,
|
||||
}}
|
||||
>
|
||||
{text}
|
||||
</Link>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'Status',
|
||||
dataIndex: 'status',
|
||||
key: 'status',
|
||||
render: (text) => {
|
||||
return text;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'Created Time',
|
||||
dataIndex: 'createdTime',
|
||||
key: 'createdTime',
|
||||
render: (text) => {
|
||||
return compatibleDayjs(text).format('YYYY-MM-DD HH:mm:ss');
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'Actions',
|
||||
dataIndex: 'Actions',
|
||||
key: 'Actions',
|
||||
render: (text, { name }) => {
|
||||
return (
|
||||
<Space>
|
||||
<Popconfirm
|
||||
title="Are you sure to delete this application?"
|
||||
onConfirm={() => {
|
||||
remove(name).then(({ code, data: content }) => {
|
||||
if (code === 200) {
|
||||
message.success({
|
||||
content,
|
||||
key: 'remove',
|
||||
});
|
||||
} else {
|
||||
message.error({
|
||||
content,
|
||||
key: 'remove',
|
||||
});
|
||||
}
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Button type="link" size="small" danger>
|
||||
Delete
|
||||
</Button>
|
||||
</Popconfirm>
|
||||
</Space>
|
||||
);
|
||||
},
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</Card>
|
||||
</PageContainer>
|
||||
);
|
||||
};
|
||||
@@ -98,7 +98,7 @@ export default (): React.ReactNode => {
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'Operations',
|
||||
title: 'Actions',
|
||||
dataIndex: 'current',
|
||||
render: (current, { envName, namespace }) => {
|
||||
const active = current === '*';
|
||||
@@ -113,7 +113,7 @@ export default (): React.ReactNode => {
|
||||
switchCurrenrt({ envName });
|
||||
}}
|
||||
>
|
||||
switch
|
||||
Switch
|
||||
</Button>
|
||||
<Button
|
||||
size="small"
|
||||
@@ -128,7 +128,7 @@ export default (): React.ReactNode => {
|
||||
})
|
||||
}
|
||||
>
|
||||
update
|
||||
Update
|
||||
</Button>
|
||||
{defaultEnv ? undefined : (
|
||||
<Popconfirm
|
||||
@@ -143,7 +143,7 @@ export default (): React.ReactNode => {
|
||||
}}
|
||||
>
|
||||
<Button type="link" size="small" danger>
|
||||
remove
|
||||
Remove
|
||||
</Button>
|
||||
</Popconfirm>
|
||||
)}
|
||||
|
||||
Vendored
+8
-2
@@ -8,7 +8,7 @@ declare namespace API {
|
||||
name: string;
|
||||
status?: string;
|
||||
components?: ComponentMeta[];
|
||||
createdTime?: Date;
|
||||
createdTime?: string;
|
||||
}
|
||||
|
||||
export interface ComponentMeta {
|
||||
@@ -19,7 +19,7 @@ declare namespace API {
|
||||
traits?: any[]; // ComponentTrait
|
||||
traitsNames?: string[];
|
||||
app: string;
|
||||
createdTime?: Date;
|
||||
createdTime?: string;
|
||||
}
|
||||
|
||||
interface Environment {
|
||||
@@ -33,4 +33,10 @@ declare namespace API {
|
||||
interface EnvironmentBody {
|
||||
namespace: string;
|
||||
}
|
||||
|
||||
interface Application {
|
||||
name: string;
|
||||
status: string;
|
||||
createdTime: string;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import { request } from 'umi';
|
||||
|
||||
const BASE_PATH = '/api/envs';
|
||||
|
||||
/*
|
||||
* application list: get /api/envs/{env}/apps
|
||||
*/
|
||||
export async function getApplications(
|
||||
envName: string,
|
||||
): Promise<API.VelaResponse<API.Application[]>> {
|
||||
return request(`${BASE_PATH}/${envName}/apps`);
|
||||
}
|
||||
|
||||
/*
|
||||
* delete application: delete /api/envs/{env}/apps/{app}
|
||||
*/
|
||||
export async function deleteApplication(
|
||||
envName: string,
|
||||
appName: string,
|
||||
): Promise<API.VelaResponse<string>> {
|
||||
return request(`${BASE_PATH}/${envName}/apps/${appName}`, { method: 'delete' });
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import dayjs from 'dayjs';
|
||||
import customParseFormat from 'dayjs/plugin/customParseFormat';
|
||||
import timezone from 'dayjs/plugin/timezone';
|
||||
import utc from 'dayjs/plugin/utc';
|
||||
|
||||
dayjs.extend(customParseFormat);
|
||||
dayjs.extend(utc);
|
||||
dayjs.extend(timezone);
|
||||
|
||||
const FORMAT = 'YYYY-MM-DD HH:mm:ss ZZ';
|
||||
|
||||
export default function compatibleDayjs(date: string) {
|
||||
return dayjs(date, FORMAT).tz();
|
||||
}
|
||||
@@ -76,6 +76,10 @@ func ListApplications(ctx context.Context, c client.Client, opt Option) ([]apis.
|
||||
}
|
||||
|
||||
for _, a := range appConfigList.Items {
|
||||
// ignore the deleted resource
|
||||
if a.GetDeletionGracePeriodSeconds() != nil {
|
||||
continue
|
||||
}
|
||||
applicationMeta, err := RetrieveApplicationStatusByName(ctx, c, a.Name, a.Namespace)
|
||||
if err != nil {
|
||||
return applicationMetaList, nil
|
||||
|
||||
Reference in New Issue
Block a user