@orsetra/shared-ui 1.1.19 → 1.1.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/api/addon.ts +85 -0
- package/api/application.ts +478 -0
- package/api/cluster.ts +29 -0
- package/api/component.ts +9 -0
- package/api/configs.ts +79 -0
- package/api/definitions.ts +29 -0
- package/api/env.ts +29 -0
- package/api/index.ts +16 -0
- package/api/kubernetes.ts +9 -0
- package/api/observation.ts +241 -0
- package/api/pipeline.ts +172 -0
- package/api/project.ts +86 -0
- package/api/repository.ts +77 -0
- package/api/roles.ts +15 -0
- package/api/system.ts +41 -0
- package/api/target.ts +20 -0
- package/api/user.ts +48 -0
- package/components/ui/index.ts +1 -1
- package/context/index.tsx +39 -0
- package/i18n.tsx +39 -0
- package/index.ts +7 -1
- package/locals/En/en.json +1 -0
- package/locals/Zh/zh.json +657 -0
- package/package.json +7 -1
- package/types/application.ts +6 -0
- package/types/data.ts +9 -0
- package/types/index.ts +5 -0
- package/types/layout.ts +7 -0
- package/types/menus.ts +32 -0
- package/types/permission.ts +4 -0
- package/types/react-cookies.d.ts +23 -0
- package/utils/_test/permission.test.ts +26 -0
- package/utils/cache.ts +9 -0
- package/utils/common.ts +314 -0
- package/utils/errors.ts +31 -0
- package/utils/i18n.tsx +28 -0
- package/utils/icon.tsx +42 -0
- package/utils/locale.tsx +190 -0
- package/utils/locals/En/en.json +1 -0
- package/utils/locals/Zh/zh.json +657 -0
- package/utils/permission.ts +136 -0
- package/utils/resetLogin.ts +35 -0
- package/utils/storage.ts +21 -0
- package/utils/utils.ts +216 -0
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import type { LoginUserInfo, PermissionBase } from '@/api';
|
|
2
|
+
|
|
3
|
+
export interface ResourceAction {
|
|
4
|
+
resource: string;
|
|
5
|
+
action: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export class ResourceName {
|
|
9
|
+
type: string;
|
|
10
|
+
value: string;
|
|
11
|
+
next?: ResourceName;
|
|
12
|
+
constructor(value: string) {
|
|
13
|
+
const index = value.indexOf('/', 1);
|
|
14
|
+
let node = value;
|
|
15
|
+
if (index > -1) {
|
|
16
|
+
node = value.slice(0, index);
|
|
17
|
+
}
|
|
18
|
+
const tn = node.split(':');
|
|
19
|
+
if (tn.length == 2) {
|
|
20
|
+
this.type = tn[0];
|
|
21
|
+
this.value = tn[1];
|
|
22
|
+
} else {
|
|
23
|
+
this.type = tn[0];
|
|
24
|
+
this.value = '*';
|
|
25
|
+
}
|
|
26
|
+
if (index > -1) {
|
|
27
|
+
const nextValue = value.slice(index + 1);
|
|
28
|
+
if (nextValue != '') {
|
|
29
|
+
this.next = new ResourceName(value.slice(index + 1));
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function checkPermission(
|
|
36
|
+
request?: ResourceAction,
|
|
37
|
+
project?: string,
|
|
38
|
+
userInfo?: LoginUserInfo,
|
|
39
|
+
) {
|
|
40
|
+
if (!request) {
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
if (!userInfo) {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (!userInfo.platformPermissions && !userInfo.projectPermissions) {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
// check platform permissions
|
|
51
|
+
if (!project) {
|
|
52
|
+
if (!userInfo.platformPermissions || userInfo.platformPermissions.length == 0) {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
let permissions = userInfo.platformPermissions || [];
|
|
58
|
+
|
|
59
|
+
// check project permissions
|
|
60
|
+
if (project && userInfo.projectPermissions) {
|
|
61
|
+
if (project == '?') {
|
|
62
|
+
Object.keys(userInfo.projectPermissions).map((key) => {
|
|
63
|
+
if (userInfo.projectPermissions) {
|
|
64
|
+
const perms = userInfo.projectPermissions[key];
|
|
65
|
+
if (perms) {
|
|
66
|
+
permissions = permissions.concat(perms);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
} else {
|
|
71
|
+
const userPermissions = userInfo.projectPermissions[project];
|
|
72
|
+
if (userPermissions) {
|
|
73
|
+
permissions = permissions.concat(userPermissions);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
for (let i = 0; i < permissions.length; i++) {
|
|
78
|
+
const effect = permissions[i].effect.toLowerCase();
|
|
79
|
+
if (effect == 'deny' && match(request, permissions[i])) {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
for (let i = 0; i < permissions.length; i++) {
|
|
84
|
+
const effect = permissions[i].effect.toLowerCase();
|
|
85
|
+
if ((effect == 'allow' || effect == '') && match(request, permissions[i])) {
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export function match(request: ResourceAction, permission: PermissionBase) {
|
|
93
|
+
if (!permission.actions.includes(request.action) && !permission.actions.includes('*')) {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
if (!permission.resources?.length) {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
for (let i = 0; i < permission.resources?.length; i++) {
|
|
100
|
+
if (
|
|
101
|
+
resourceMatch(new ResourceName(request.resource), new ResourceName(permission.resources[i]))
|
|
102
|
+
) {
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export function resourceMatch(requestResource: ResourceName, permissionResource: ResourceName) {
|
|
110
|
+
let current: undefined | ResourceName = permissionResource;
|
|
111
|
+
let targetCurrent: undefined | ResourceName = requestResource;
|
|
112
|
+
while (current && current.type) {
|
|
113
|
+
if (current.type == '*') {
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
116
|
+
if (!targetCurrent || !targetCurrent.type) {
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
if (current.type != targetCurrent.type) {
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
if (
|
|
123
|
+
current.value != targetCurrent.value &&
|
|
124
|
+
current.value != '*' &&
|
|
125
|
+
targetCurrent.value != '?'
|
|
126
|
+
) {
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
current = current.next;
|
|
130
|
+
targetCurrent = targetCurrent.next;
|
|
131
|
+
}
|
|
132
|
+
if (targetCurrent && targetCurrent.type) {
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
return true;
|
|
136
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import i18n from '../i18n';
|
|
4
|
+
|
|
5
|
+
class ResetLogin {
|
|
6
|
+
private static singleton: ResetLogin;
|
|
7
|
+
public reset: React.ReactNode | null;
|
|
8
|
+
constructor() {
|
|
9
|
+
this.reset = this.resetDom();
|
|
10
|
+
}
|
|
11
|
+
private resetDom(): React.ReactNode | null {
|
|
12
|
+
// Check if running in browser environment
|
|
13
|
+
if (typeof window === 'undefined') {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (window.location.href.indexOf('/login') === -1) {
|
|
18
|
+
// Trigger logout and redirect
|
|
19
|
+
localStorage.removeItem('token');
|
|
20
|
+
localStorage.removeItem('refreshToken');
|
|
21
|
+
window.location.href = '/login';
|
|
22
|
+
return null;
|
|
23
|
+
} else {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
static getInstance() {
|
|
28
|
+
if (!ResetLogin.singleton) {
|
|
29
|
+
ResetLogin.singleton = new ResetLogin();
|
|
30
|
+
}
|
|
31
|
+
return ResetLogin.singleton;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export default ResetLogin;
|
package/utils/storage.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const token_key = 'token';
|
|
2
|
+
|
|
3
|
+
export function getToken() {
|
|
4
|
+
return localStorage.getItem(token_key) || '';
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function setToken(token: string | string[]) {
|
|
8
|
+
if (Array.isArray(token)) {
|
|
9
|
+
localStorage.setItem(token_key, token[0]);
|
|
10
|
+
} else if (typeof token === 'string') {
|
|
11
|
+
localStorage.setItem(token_key, token);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function removeToken() {
|
|
16
|
+
localStorage.removeItem(token_key);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function hasToken() {
|
|
20
|
+
return !!getToken();
|
|
21
|
+
}
|
package/utils/utils.ts
ADDED
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import _ from 'lodash';
|
|
2
|
+
|
|
3
|
+
import type { ComponentDefinitionsBase,Endpoint } from '@/api';
|
|
4
|
+
|
|
5
|
+
type SelectGroupType = Array<{
|
|
6
|
+
label: string;
|
|
7
|
+
children: Array<{ label: string; value: string }>;
|
|
8
|
+
}>;
|
|
9
|
+
|
|
10
|
+
// code from https://github.com/kubernetes-client/javascript/blob/master/src/util.ts#L17
|
|
11
|
+
export function findSuffix(quantity: string): string {
|
|
12
|
+
let ix = quantity.length - 1;
|
|
13
|
+
while (ix >= 0 && !/[\.0-9]/.test(quantity.charAt(ix))) {
|
|
14
|
+
ix--;
|
|
15
|
+
}
|
|
16
|
+
return ix === -1 ? '' : quantity.substring(ix + 1);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// code from https://github.com/kubernetes-client/javascript/blob/master/src/util.ts#L17
|
|
20
|
+
export function quantityToScalar(quantity: string): number | bigint {
|
|
21
|
+
if (!quantity) {
|
|
22
|
+
return 0;
|
|
23
|
+
}
|
|
24
|
+
const suffix = findSuffix(quantity);
|
|
25
|
+
if (suffix === '') {
|
|
26
|
+
const num = Number(quantity).valueOf();
|
|
27
|
+
if (isNaN(num)) {
|
|
28
|
+
throw new Error('Unknown quantity ' + quantity);
|
|
29
|
+
}
|
|
30
|
+
return num;
|
|
31
|
+
}
|
|
32
|
+
switch (suffix) {
|
|
33
|
+
case 'n':
|
|
34
|
+
return Number(quantity.substr(0, quantity.length - 1)).valueOf() / 100_000_000.0;
|
|
35
|
+
case 'm':
|
|
36
|
+
return Number(quantity.substr(0, quantity.length - 1)).valueOf() / 1000.0;
|
|
37
|
+
case 'Ki':
|
|
38
|
+
return BigInt(quantity.substr(0, quantity.length - 2)) * BigInt(1024);
|
|
39
|
+
case 'Mi':
|
|
40
|
+
return BigInt(quantity.substr(0, quantity.length - 2)) * BigInt(1024 * 1024);
|
|
41
|
+
case 'Gi':
|
|
42
|
+
return BigInt(quantity.substr(0, quantity.length - 2)) * BigInt(1024 * 1024 * 1024);
|
|
43
|
+
case 'Ti':
|
|
44
|
+
return (
|
|
45
|
+
BigInt(quantity.substr(0, quantity.length - 2)) * BigInt(1024 * 1024 * 1024) * BigInt(1024)
|
|
46
|
+
);
|
|
47
|
+
case 'Pi':
|
|
48
|
+
return (
|
|
49
|
+
BigInt(quantity.substr(0, quantity.length - 2)) *
|
|
50
|
+
BigInt(1024 * 1024 * 1024) *
|
|
51
|
+
BigInt(1024 * 1024)
|
|
52
|
+
);
|
|
53
|
+
case 'Ei':
|
|
54
|
+
return (
|
|
55
|
+
BigInt(quantity.substr(0, quantity.length - 2)) *
|
|
56
|
+
BigInt(1024 * 1024 * 1024) *
|
|
57
|
+
BigInt(1024 * 1024 * 1024)
|
|
58
|
+
);
|
|
59
|
+
default:
|
|
60
|
+
throw new Error(`Unknown suffix: ${suffix}`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function transComponentDefinitions(componentDefinitions: ComponentDefinitionsBase[]) {
|
|
65
|
+
const defaultCoreDataSource = ['k8s-objects', 'task', 'webservice', 'worker'];
|
|
66
|
+
const cloud: SelectGroupType = [
|
|
67
|
+
{
|
|
68
|
+
label: 'Cloud',
|
|
69
|
+
children: [],
|
|
70
|
+
},
|
|
71
|
+
];
|
|
72
|
+
const core: SelectGroupType = [
|
|
73
|
+
{
|
|
74
|
+
label: 'Core',
|
|
75
|
+
children: [],
|
|
76
|
+
},
|
|
77
|
+
];
|
|
78
|
+
const custom: SelectGroupType = [
|
|
79
|
+
{
|
|
80
|
+
label: 'Custom',
|
|
81
|
+
children: [],
|
|
82
|
+
},
|
|
83
|
+
];
|
|
84
|
+
(componentDefinitions || []).map((item: { name: string; workloadType?: string }) => {
|
|
85
|
+
if (item.workloadType === 'configurations.terraform.core.oam.dev') {
|
|
86
|
+
cloud[0].children.push({
|
|
87
|
+
label: item.name,
|
|
88
|
+
value: item.name,
|
|
89
|
+
});
|
|
90
|
+
} else if (defaultCoreDataSource.includes(item.name)) {
|
|
91
|
+
core[0].children.push({
|
|
92
|
+
label: item.name,
|
|
93
|
+
value: item.name,
|
|
94
|
+
});
|
|
95
|
+
} else {
|
|
96
|
+
custom[0].children.push({
|
|
97
|
+
label: item.name,
|
|
98
|
+
value: item.name,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
return [...core, ...custom, ...cloud];
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export function getLink(endpointObj: Endpoint) {
|
|
106
|
+
const { appProtocol, host } = endpointObj.endpoint;
|
|
107
|
+
let { port, protocol = '', path = '' } = endpointObj.endpoint;
|
|
108
|
+
protocol = protocol.toLocaleLowerCase();
|
|
109
|
+
if (appProtocol && appProtocol !== '') {
|
|
110
|
+
protocol = appProtocol;
|
|
111
|
+
}
|
|
112
|
+
// Support to open this address in a new window directly.
|
|
113
|
+
if (protocol == 'tcp') {
|
|
114
|
+
protocol = 'http';
|
|
115
|
+
}
|
|
116
|
+
if (host == '') {
|
|
117
|
+
return path;
|
|
118
|
+
}
|
|
119
|
+
if (path === '/') {
|
|
120
|
+
path = '';
|
|
121
|
+
}
|
|
122
|
+
if ((protocol === 'https' && port == 443) || (protocol === 'http' && port === 80)) {
|
|
123
|
+
port = '';
|
|
124
|
+
} else {
|
|
125
|
+
port = ':' + port;
|
|
126
|
+
}
|
|
127
|
+
return protocol + '://' + host + port + path;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export function getValue(key: string, value: any): any {
|
|
131
|
+
if (key.indexOf('.') > -1) {
|
|
132
|
+
const currentKey: string = key.substring(0, key.indexOf('.'));
|
|
133
|
+
const nextKey: string = key.substring(key.indexOf('.') + 1);
|
|
134
|
+
return getValue(nextKey, value[currentKey]);
|
|
135
|
+
}
|
|
136
|
+
if (!value) {
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
return value[key];
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export function getSelectLabel(
|
|
143
|
+
data: Array<{ name: string; alias?: string }>,
|
|
144
|
+
): Array<{ label: string; value: string }> {
|
|
145
|
+
return (data || []).map((item: { name: string; alias?: string }) => {
|
|
146
|
+
return { label: item.alias || item.name, value: item.name };
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export function getMatchParamObj(match: { params: any }, name: string) {
|
|
151
|
+
return match.params && match.params[name];
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Get browser name agent version
|
|
156
|
+
* return browser name version
|
|
157
|
+
* */
|
|
158
|
+
export function getBrowserNameAndVersion() {
|
|
159
|
+
// Check if running in browser environment
|
|
160
|
+
if (typeof window === 'undefined' || typeof navigator === 'undefined') {
|
|
161
|
+
return 'unknown';
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const agent = navigator.userAgent.toLowerCase();
|
|
165
|
+
const regStr_ie = /msie [\d.]+/gi;
|
|
166
|
+
const regStr_ff = /firefox\/[\d.]+/gi;
|
|
167
|
+
const regStr_chrome = /chrome\/[\d.]+/gi;
|
|
168
|
+
const regStr_saf = /safari\/[\d.]+/gi;
|
|
169
|
+
let browserNV: any;
|
|
170
|
+
//IE
|
|
171
|
+
if (agent.indexOf('msie') > 0) {
|
|
172
|
+
browserNV = agent.match(regStr_ie);
|
|
173
|
+
}
|
|
174
|
+
//firefox
|
|
175
|
+
if (agent.indexOf('firefox') > 0) {
|
|
176
|
+
browserNV = agent.match(regStr_ff);
|
|
177
|
+
}
|
|
178
|
+
//Chrome
|
|
179
|
+
if (agent.indexOf('chrome') > 0) {
|
|
180
|
+
browserNV = agent.match(regStr_chrome);
|
|
181
|
+
}
|
|
182
|
+
//Safari
|
|
183
|
+
if (agent.indexOf('safari') > 0 && agent.indexOf('chrome') < 0) {
|
|
184
|
+
browserNV = agent.match(regStr_saf);
|
|
185
|
+
}
|
|
186
|
+
browserNV = browserNV.toString();
|
|
187
|
+
//other
|
|
188
|
+
if ('' == browserNV) {
|
|
189
|
+
browserNV = 'Is not a standard browser';
|
|
190
|
+
}
|
|
191
|
+
//Here does not display "/"
|
|
192
|
+
if (browserNV.indexOf('firefox') != -1 || browserNV.indexOf('chrome') != -1) {
|
|
193
|
+
browserNV = browserNV.replace('/', '');
|
|
194
|
+
}
|
|
195
|
+
//Here does not display space
|
|
196
|
+
if (browserNV.indexOf('msie') != -1) {
|
|
197
|
+
//msie replace IE & trim space
|
|
198
|
+
browserNV = browserNV.replace('msie', 'ie').replace(/\s/g, '');
|
|
199
|
+
}
|
|
200
|
+
//return eg:ie9.0 firefox34.0 chrome37.0
|
|
201
|
+
return browserNV;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export function downloadStringFile(content: string, filename: string) {
|
|
205
|
+
// Check if running in browser environment
|
|
206
|
+
if (typeof window === 'undefined' || typeof document === 'undefined') {
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const element = document.createElement("a");
|
|
211
|
+
const file = new Blob([content], {type: 'text/plain'});
|
|
212
|
+
element.href = URL.createObjectURL(file);
|
|
213
|
+
element.download = filename;
|
|
214
|
+
document.body.appendChild(element);
|
|
215
|
+
element.click();
|
|
216
|
+
}
|