Refactor UI with vue3

This commit is contained in:
cuigh
2021-12-06 20:24:22 +08:00
parent afbc618abb
commit 2dd9cd15e1
411 changed files with 22726 additions and 69351 deletions

116
ui/src/api/ajax.ts Normal file
View File

@@ -0,0 +1,116 @@
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios'
import { store } from "../store";
import { router } from "../router/router";
import { Mutations } from "@/store/mutations";
import { t, te } from '@/locales';
// export interface AjaxOptions {
// }
export interface Result<T> {
code: number;
info?: string;
data?: T;
}
class Ajax {
private ajax: AxiosInstance;
constructor() {
this.ajax = axios.create({
baseURL: import.meta.env.MODE === 'development' ? '/api' : '/api',
timeout: 10000,
// withCredentials: true,
})
this.ajax.interceptors.request.use(
(config: any) => {
if (store.state.token) {
config.headers.Authorization = "Bearer " + store.state.token
}
// store.commit(Mutations.SetAjaxLoading, true);
return config;
},
(error: any) => {
console.error(error); // for debug
return Promise.reject(error);
}
)
this.ajax.interceptors.response.use(
(response: any) => {
if (response.headers.authorization) {
store.commit(Mutations.SetToken, response.headers.authorization)
}
// store.commit(Mutations.SetAjaxLoading, false);
return response;
},
(error: any) => {
if (this.handleError(error)) {
// Stop Promise chain
return new Promise(() => { })
} else {
return Promise.reject(error)
}
}
)
}
private handleError(error: any): boolean {
if (error.response) {
switch (error.response.status) {
case 401:
store.commit(Mutations.Logout);
if (error.config.method === "get") {
router.replace({
name: 'login',
query: {
redirect: router.currentRoute.value.fullPath
}
});
} else {
this.showError(error)
}
return true
case 403:
router.replace("/403");
return true
case 500:
this.showError(error)
}
} else {
window.message.error(error.message, { duration: 5000 });
}
return false
}
private showError(error: any) {
const code = error.response.data?.code || 1;
const info = te('errors.'+code) ? t('errors.'+code) : error.response.data?.info || error.message;
window.message.error(info, { duration: 5000 });
}
async get<T>(url: string, args?: any, config?: AxiosRequestConfig): Promise<Result<T>> {
config = { ...config, params: args }
const r = await this.ajax.get<Result<T>>(url, config);
return r.data;
}
async post<T>(url: string, data?: any, config?: AxiosRequestConfig): Promise<Result<T>> {
config = { ...config, headers: { 'Content-Type': 'application/json' } }
// Object.assign(config || {}, {
// headers: {
// 'Content-Type': 'application/json',
// },
// })
const r = await this.ajax.post<Result<T>>(url, data, config);
return r.data;
}
async request<T>(config: AxiosRequestConfig): Promise<Result<T>> {
const r = await this.ajax.request<Result<T>>(config);
return r.data;
}
}
export default new Ajax;

92
ui/src/api/chart.ts Normal file
View File

@@ -0,0 +1,92 @@
import ajax, { Result } from './ajax'
export interface Chart {
id: string;
title: string;
desc: string;
metrics: {
legend: string;
query: string;
}[];
kind?: string;
dashboard: string;
type: string;
unit: string;
width: number;
height: number;
margin: {
left: number;
right: number;
top: number;
bottom: number;
};
createdAt: string;
updatedAt: string;
}
export interface Dashboard {
name: string;
key: string;
period: number;
interval: number;
charts: ChartInfo[];
}
export interface ChartInfo {
id: string;
title: string;
type: 'line' | 'bar' | 'pie' | 'gauge';
unit: string;
width: number;
height: number;
margin: {
left?: number;
right?: number;
top?: number;
bottom?: number;
};
}
export interface SearchArgs {
name?: string;
dashboard?: string;
pageIndex: number;
pageSize: number;
}
export interface SearchResult {
items: Chart[];
total: number;
}
export class ChartApi {
search(args: SearchArgs) {
return ajax.get<SearchResult>('/chart/search', args)
}
save(chart: Chart) {
return ajax.post<Result<Object>>('/chart/save', chart)
}
find(id: string) {
return ajax.get<Chart>('/chart/find', { id })
}
delete(id: string, title: string) {
return ajax.post<Result<Object>>('/chart/delete', { id, title })
}
fetchData(key: string, charts: string[], period: number) {
return ajax.get<any>('/chart/fetch-data', { key, charts: charts.join(","), period })
}
findDashboard(name: string, key: string) {
return ajax.get<Dashboard>('/chart/find-dashboard', { name, key })
}
saveDashboard(dashboard: Dashboard) {
return ajax.post<Result<Object>>('/chart/save-dashboard', dashboard)
}
}
export default new ChartApi

57
ui/src/api/config.ts Normal file
View File

@@ -0,0 +1,57 @@
import ajax, { Result } from './ajax'
export interface Config {
id: string;
name: string;
data: string;
version: number;
labels?: {
name: string;
value: string;
}[];
templating: {
name: string;
options?: {
name: string;
value: string;
}[];
}
createdAt: string;
updatedAt: string;
}
export interface SearchArgs {
name?: string;
pageIndex: number;
pageSize: number;
}
export interface SearchResult {
items: Config[];
total: number;
}
export interface FindResult {
config: Config;
raw: string;
}
export class ConfigApi {
find(id: string) {
return ajax.get<FindResult>('/config/find', { id })
}
search(args: SearchArgs) {
return ajax.get<SearchResult>('/config/search', args)
}
save(c: Config) {
return ajax.post<Result<Object>>('/config/save', c)
}
delete(id: string) {
return ajax.post<Result<Object>>('/config/delete', { id })
}
}
export default new ConfigApi

82
ui/src/api/container.ts Normal file
View File

@@ -0,0 +1,82 @@
import ajax, { Result } from './ajax'
export interface Container {
id: string;
pid: number;
name: string;
image: string;
command: string;
createdAt: string;
startedAt: string;
sizeRw: number;
sizeRootFs: number;
state: string;
status: string;
networkMode: string;
ports?: {
ip: string;
privatePort: number;
publicPort: number;
type: string;
}[];
mounts?: {
type: string;
name: string;
source: string;
destination: string;
driver: string;
mode: string;
rw: boolean;
propagation: string;
}[];
labels?: {
name: string;
value: string;
}[];
}
export interface SearchArgs {
name?: string;
status?: string;
pageIndex: number;
pageSize: number;
}
export interface SearchResult {
items: Container[];
total: number;
}
export interface FindResult {
container: Container;
raw: string;
}
export interface FetchLogsArgs {
id: string;
lines: number;
timestamps: boolean;
}
export class ContainerApi {
find(id: string) {
return ajax.get<FindResult>('/container/find', { id })
}
search(args: SearchArgs) {
return ajax.get<SearchResult>('/container/search', args)
}
delete(id: string, name: string) {
return ajax.post<Result<Object>>('/container/delete', { id, name })
}
fetchLogs(args: FetchLogsArgs) {
return ajax.get<{
stdout: string;
stderr: string;
}>('/container/fetch-logs', args)
}
}
export default new ContainerApi

32
ui/src/api/event.ts Normal file
View File

@@ -0,0 +1,32 @@
import ajax, { Result } from './ajax'
export interface Event {
id: string;
type: string;
action: string;
code: number;
name: string;
userId: string;
username: string;
time: string;
}
export interface SearchArgs {
type?: string;
name?: string;
pageIndex: number;
pageSize: number;
}
export interface SearchResult {
items: Event[];
total: number;
}
export class EventApi {
search(args: SearchArgs) {
return ajax.get<SearchResult>('/event/search', args)
}
}
export default new EventApi

78
ui/src/api/image.ts Normal file
View File

@@ -0,0 +1,78 @@
import ajax, { Result } from './ajax'
export interface Image {
id: string;
pid: string;
created: string;
containers: number;
digests: string[];
tags: string[];
labels?: {
name: string;
value: string;
}[];
size: number;
sharedSize: number;
virtualSize: number;
comment: string;
container: string;
dockerVersion: string;
author: string;
variant: string;
arch: string;
os: string;
osVersion: string;
lastTagTime: string;
graphDriver?: {
name?: string;
data?: {
name: string;
value: string;
}[];
};
rootFS?: {
type?: string;
layers?: string[];
baseLayer?: string;
};
histories?: {
id: string;
comment: string;
size: number;
tags: string[];
createdAt: string;
createdBy: string;
}[];
}
export interface SearchArgs {
name?: string;
pageIndex: number;
pageSize: number;
}
export interface SearchResult {
items: Image[];
total: number;
}
export interface FindResult {
image: Image;
raw: string;
}
export class ImageApi {
find(id: string) {
return ajax.get<FindResult>('/image/find', { id })
}
search(args: SearchArgs) {
return ajax.get<SearchResult>('/image/search', args)
}
delete(id: string, name: string) {
return ajax.post<Result<Object>>('/image/delete', { id, name })
}
}
export default new ImageApi

66
ui/src/api/network.ts Normal file
View File

@@ -0,0 +1,66 @@
import ajax, { Result } from './ajax'
export interface Network {
id: string;
name: string;
created: string;
scope: string;
driver: string;
internal: boolean;
attachable: boolean;
ingress: boolean;
ipv6: boolean;
ipam: {
driver: string;
options: [];
config: {
subnet: string;
gateway: string;
range: string;
}[],
}
options?: {
name: string;
value: string;
}[];
labels?: {
name: string;
value: string;
}[];
containers?: {
id: string;
name: string;
mac: string;
ipv4: string;
ipv6: string;
}[];
}
export interface FindResult {
network: Network;
raw: string;
}
export class NetworkApi {
find(name: string) {
return ajax.get<FindResult>('/network/find', { name })
}
search() {
return ajax.get<Network[]>('/network/search')
}
save(network: Network) {
return ajax.post<Result<Object>>('/network/save', network)
}
delete(id: string, name: string) {
return ajax.post<Result<Object>>('/network/delete', { id, name })
}
disconnect(networkId: string, networkName: string, container: string) {
return ajax.post<Result<Object>>('/network/disconnect', { networkId, networkName, container })
}
}
export default new NetworkApi

53
ui/src/api/node.ts Normal file
View File

@@ -0,0 +1,53 @@
import ajax, { Result } from './ajax'
export interface Node {
id: string;
name?: string;
hostname: string;
version: number;
role: string;
availability: string;
engineVersion: string;
arch: string;
os: string;
cpu: number;
memory: number;
address: string;
state: string;
labels?: {
name: string;
value: string;
}[];
manager?: {
leader: boolean;
reachability: string;
addr: string;
};
createdAt: string;
updatedAt: string;
}
export interface FindResult {
node: Node;
raw: string;
}
export class NodeApi {
find(id: string) {
return ajax.get<FindResult>('/node/find', { id })
}
search() {
return ajax.get<Node[]>('/node/search')
}
save(node: Node) {
return ajax.post<Result<Object>>('/node/save', node)
}
delete(id: string) {
return ajax.post<Result<Object>>('/node/delete', { id })
}
}
export default new NodeApi

31
ui/src/api/registry.ts Normal file
View File

@@ -0,0 +1,31 @@
import ajax, { Result } from './ajax'
export interface Registry {
id: string;
name: string;
url: string;
username: string;
password: string;
createdAt: number;
updatedAt: number;
}
export class RegistryApi {
find(id: string) {
return ajax.get<Registry>('/registry/find', { id })
}
search() {
return ajax.get<Registry[]>('/registry/search')
}
save(registry: Registry) {
return ajax.post<Result<Object>>('/registry/save', registry)
}
delete(id: string) {
return ajax.post<Result<Object>>('/registry/delete', { id })
}
}
export default new RegistryApi

30
ui/src/api/role.ts Normal file
View File

@@ -0,0 +1,30 @@
import ajax, { Result } from './ajax'
export interface Role {
id: string;
name: string;
desc: string;
perms: string[];
createdAt: string;
updatedAt: string;
}
export class RoleApi {
find(id: string) {
return ajax.get<Role>('/role/find', { id })
}
search(name?: string) {
return ajax.get<Role[]>('/role/search', { name })
}
save(role: Role) {
return ajax.post<Result<Object>>('/role/save', role)
}
delete(id: string, name: string) {
return ajax.post<Result<Object>>('/role/delete', { id, name })
}
}
export default new RoleApi

64
ui/src/api/secret.ts Normal file
View File

@@ -0,0 +1,64 @@
import ajax, { Result } from './ajax'
export interface Secret {
id: string;
name: string;
data: string;
version: number;
labels?: {
name: string;
value: string;
}[];
driver: {
name: string;
options?: {
name: string;
value: string;
}[];
}
templating: {
name: string;
options?: {
name: string;
value: string;
}[];
}
createdAt: string;
updatedAt: string;
}
export interface SearchArgs {
name?: string;
pageIndex: number;
pageSize: number;
}
export interface SearchResult {
items: Secret[];
total: number;
}
export interface FindResult {
secret: Secret;
raw: string;
}
export class SecretApi {
find(id: string) {
return ajax.get<FindResult>('/secret/find', { id })
}
search(args: SearchArgs) {
return ajax.get<SearchResult>('/secret/search', args)
}
save(c: Secret) {
return ajax.post<Result<Object>>('/secret/save', c)
}
delete(id: string) {
return ajax.post<Result<Object>>('/secret/delete', { id })
}
}
export default new SecretApi

184
ui/src/api/service.ts Normal file
View File

@@ -0,0 +1,184 @@
import ajax, { Result } from './ajax'
export interface Service {
id: string;
name: string;
image: string;
version: number;
mode: string;
command: string;
args: string;
dir: string;
user: string;
replicas: number;
runningTasks: number;
desiredTasks: number;
completedTasks: number;
networks: string[],
labels?: {
name: string;
value: string;
}[];
containerLabels?: {
name: string;
value: string;
}[];
env?: {
name: string;
value: string;
}[];
update?: {
state?: string;
message?: string;
};
endpoint: {
mode: string;
ports: {
name: string;
protocol: string;
mode: string;
targetPort: string;
publishedPort: string;
}[],
vips: {
id: string;
name: string;
ip: string;
}[],
},
mounts?: {
type: string;
source: string;
target: string;
readonly: boolean;
consistency: string;
}[];
resource: {
limit: {
cpu: number;
memory: string;
};
reserve: {
cpu: number;
memory: string;
};
};
placement: {
constraints: {
name: string;
value: string;
op: string;
}[];
preferences: string[];
};
configs?: {
key: string;
path: string;
uid: string;
gid: string;
mode: number;
}[];
secrets?: {
key: string;
path: string;
uid: string;
gid: string;
mode: number;
}[];
updatePolicy: {
parallelism: number;
delay: string;
failureAction: string;
order: string;
};
rollbackPolicy: {
parallelism: number;
delay: string;
failureAction: string;
order: string;
};
restartPolicy: {
condition: string;
maxAttempts: number;
delay: string;
window: string;
};
logDriver: {
name: string;
options?: {
name: string;
value: string;
}[];
}
dns: {
servers: string[];
search: string[];
options: string[];
}
hosts: string[];
hostname: string;
createdAt: string;
updatedAt: string;
}
export interface SearchArgs {
name?: string;
mode?: string;
pageIndex: number;
pageSize: number;
}
export interface SearchResult {
items: Service[];
total: number;
}
export interface FindResult {
service: Service;
raw: string;
}
export interface FetchLogsArgs {
id: string;
lines: number;
timestamps: boolean;
}
export class ServiceApi {
find(name: string, status: boolean = false) {
return ajax.get<FindResult>('/service/find', { name, status })
}
search(args: SearchArgs) {
return ajax.get<SearchResult>('/service/search', args)
}
save(service: Service) {
return ajax.post<Result<Object>>('/service/save', service)
}
delete(name: string) {
return ajax.post<Result<Object>>('/service/delete', { name })
}
restart(name: string) {
return ajax.post<Result<Object>>('/service/restart', { name })
}
rollback(name: string) {
return ajax.post<Result<Object>>('/service/rollback', { name })
}
scale(name: string, count: number, version: number) {
return ajax.post<Result<Object>>('/service/scale', { name, count, version })
}
fetchLogs(args: FetchLogsArgs) {
return ajax.get<{
stdout: string;
stderr: string;
}>('/service/fetch-logs', args)
}
}
export default new ServiceApi

43
ui/src/api/setting.ts Normal file
View File

@@ -0,0 +1,43 @@
import ajax, { Result } from './ajax'
export interface Setting {
region: RegionSetting;
ldap: LdapSetting;
metric: MetricSetting;
}
export interface RegionSetting {
lang: string;
timezone: number;
}
export interface LdapSetting {
enabled: boolean;
address: string;
security: number;
auth: string;
bind_dn: string;
bind_pwd: string;
base_dn: string;
user_dn: string;
user_filter: string;
name_attr: string;
email_attr: string
}
export interface MetricSetting {
prometheus: string;
}
export class SettingApi {
load() {
return ajax.get<Setting>('/setting/load')
}
save(id: string, options: Object) {
console.log({ id, options })
return ajax.post<Result<Object>>('/setting/save', { id, options })
}
}
export default new SettingApi

46
ui/src/api/stack.ts Normal file
View File

@@ -0,0 +1,46 @@
import ajax, { Result } from './ajax'
export interface Stack {
id: string;
name: string;
content: string;
services?: string[];
internal: boolean;
createdAt: string;
createdBy: string;
updatedAt: string;
updatedBy: string;
}
export interface SearchArgs {
name?: string;
filter?: string;
}
export class StackApi {
find(name: string) {
return ajax.get<Stack>('/stack/find', { name })
}
search(args: SearchArgs) {
return ajax.get<Stack[]>('/stack/search', args)
}
save(s: Stack) {
return ajax.post<Result<Object>>('/stack/save', s)
}
delete(name: string) {
return ajax.post<Result<Object>>('/stack/delete', { name })
}
shutdown(name: string) {
return ajax.post<Result<Object>>('/stack/shutdown', { name })
}
deploy(name: string) {
return ajax.post<Result<Object>>('/stack/deploy', { name })
}
}
export default new StackApi

46
ui/src/api/system.ts Normal file
View File

@@ -0,0 +1,46 @@
import ajax, { Result } from './ajax'
export interface User {
loginName: string;
password: string;
name: string;
email: string;
}
export interface State {
fresh: boolean;
}
export interface Version {
version: string;
goVersion: string;
}
export interface Summary {
version: string;
goVersion: string;
nodeCount: number;
networkCount: number;
serviceCount: number;
stackCount: number;
}
export class SystemApi {
checkState() {
return ajax.get<State>('/system/check-state')
}
createAdmin(user: User) {
return ajax.post<Result<Object>>('/system/create-admin', user)
}
version() {
return ajax.get<Version>('/system/version')
}
summarize() {
return ajax.get<Summary>('/system/summarize')
}
}
export default new SystemApi

76
ui/src/api/task.ts Normal file
View File

@@ -0,0 +1,76 @@
import ajax, { Result } from './ajax'
export interface Task {
id: string;
name: string;
version: number;
image: string;
slot: number;
state: string;
serviceId: string;
serviceName: string;
nodeId: string;
containerId?: string;
pid?: number;
exitCode?: number;
message: string;
error: string;
env?: {
name: string;
value: string;
}[];
labels?: {
name: string;
value: string;
}[];
networks?: {
id: string;
name: string;
ips: string[];
}[];
createdAt: string;
updatedAt: string;
}
export interface SearchArgs {
node?: string;
service?: string;
state?: string;
pageIndex: number;
pageSize: number;
}
export interface SearchResult {
items: Task[];
total: number;
}
export interface FindResult {
task: Task;
raw: string;
}
export interface FetchLogsArgs {
id: string;
lines: number;
timestamps: boolean;
}
export class TaskApi {
find(id: string) {
return ajax.get<FindResult>('/task/find', { id })
}
search(args: SearchArgs) {
return ajax.get<SearchResult>('/task/search', args)
}
fetchLogs(args: FetchLogsArgs) {
return ajax.get<{
stdout: string;
stderr: string;
}>('/task/fetch-logs', args)
}
}
export default new TaskApi

90
ui/src/api/user.ts Normal file
View File

@@ -0,0 +1,90 @@
import ajax, { Result } from './ajax'
export interface AuthUser {
token: string;
id: string;
name: string;
}
export interface User {
id: string;
name: string;
loginName: string;
password: string;
passwordConfirm?: string;
admin: boolean;
type: string;
status: number;
email: string;
createdAt: string;
updatedAt: string;
roles: string[];
}
export interface LoginArgs {
name: string;
password: string;
}
export interface SearchArgs {
name?: string;
loginName?: string;
filter?: string;
pageIndex: number;
pageSize: number;
}
export interface SearchResult {
items: User[];
total: number;
}
export interface SetStatusArgs {
id: string;
status: number;
}
export interface ModifyPasswordArgs {
oldPwd: string;
newPwd: string;
}
export class UserApi {
login(args: LoginArgs) {
return ajax.post<AuthUser>('/user/sign-in', args)
}
save(user: User) {
return ajax.post<Result<Object>>('/user/save', user)
}
find(id: string) {
return ajax.get<User>('/user/find', { id })
}
fetch(ids: string[]) {
return ajax.get<User[]>('/user/fetch', { ids: ids.join(',') })
}
search(args: SearchArgs) {
return ajax.get<SearchResult>('/user/search', args)
}
setStatus(args: SetStatusArgs) {
return ajax.post<Result<Object>>('/user/set-status', args)
}
delete(id: string, name: string) {
return ajax.post<Result<Object>>('/user/delete', { id, name })
}
modifyPassword(args: ModifyPasswordArgs) {
return ajax.post<Result<Object>>('/user/modify-password', args)
}
modifyProfile(user: User) {
return ajax.post<Result<Object>>('/user/modify-profile', user)
}
}
export default new UserApi

65
ui/src/api/volume.ts Normal file
View File

@@ -0,0 +1,65 @@
import ajax, { Result } from './ajax'
export interface Volume {
name: string;
driver: string;
customDriver: string;
mountPoint: string;
createdAt: string;
scope: string;
refCount: number;
size: number;
labels?: {
name: string;
value: string;
}[];
options?: {
name: string;
value: string;
}[];
}
export interface SearchArgs {
name?: string;
pageIndex: number;
pageSize: number;
}
export interface SearchResult {
items: Volume[];
total: number;
}
export interface FindResult {
volume: Volume;
raw: string;
}
export interface PruneResult {
deletedVolumes: string[];
reclaimedSpace: number;
}
export class VolumeApi {
find(name: string) {
return ajax.get<FindResult>('/volume/find', { name })
}
search(args: SearchArgs) {
return ajax.get<SearchResult>('/volume/search', args)
}
delete(name: string) {
return ajax.post<Result<Object>>('/volume/delete', { name })
}
save(v: Volume) {
return ajax.post<Result<Object>>('/volume/save', v)
}
prune() {
return ajax.post<PruneResult>('/volume/prune')
}
}
export default new VolumeApi