@jfvilas/plugin-kwirth-log 0.12.8 → 0.13.0
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/README.md +47 -4
- package/dist/api/KwirthLogClient.esm.js +4 -56
- package/dist/api/KwirthLogClient.esm.js.map +1 -1
- package/dist/api/types.esm.js.map +1 -1
- package/dist/components/{EntityKwirthLogContent/EntityKwirthLogContent.esm.js → EntityKwirthLogContent.esm.js} +119 -50
- package/dist/components/EntityKwirthLogContent.esm.js.map +1 -0
- package/dist/components/Options.esm.js +20 -0
- package/dist/components/Options.esm.js.map +1 -0
- package/dist/index.d.ts +16 -6
- package/dist/index.esm.js +4 -0
- package/dist/index.esm.js.map +1 -1
- package/dist/plugin.esm.js +1 -1
- package/dist/plugin.esm.js.map +1 -1
- package/dist/routes.esm.js.map +1 -1
- package/package.json +1 -1
- package/dist/assets/kwirth-log-component-not-found.svg +0 -30
- package/dist/components/ClusterList/ClusterList.esm.js +0 -30
- package/dist/components/ClusterList/ClusterList.esm.js.map +0 -1
- package/dist/components/ComponentNotFound/ComponentNotFound.esm.js +0 -64
- package/dist/components/ComponentNotFound/ComponentNotFound.esm.js.map +0 -1
- package/dist/components/EntityKwirthLogContent/EntityKwirthLogContent.esm.js.map +0 -1
- package/dist/components/EntityKwirthLogContent/index.esm.js +0 -2
- package/dist/components/EntityKwirthLogContent/index.esm.js.map +0 -1
- package/dist/components/ObjectSelector/ObjectSelector.esm.js +0 -84
- package/dist/components/ObjectSelector/ObjectSelector.esm.js.map +0 -1
- package/dist/components/Options/Options.esm.js +0 -20
- package/dist/components/Options/Options.esm.js.map +0 -1
- package/dist/components/StatusLog/StatusLog.esm.js +0 -10
- package/dist/components/StatusLog/StatusLog.esm.js.map +0 -1
package/README.md
CHANGED
|
@@ -43,9 +43,10 @@ Following table shows version compatibility between this Kwirth Backstage plugin
|
|
|
43
43
|
|
|
44
44
|
| Plugin Kwirth version | Kwirth version |
|
|
45
45
|
|-|-|
|
|
46
|
-
|0.
|
|
47
|
-
|0.12.5|0.4.20|
|
|
46
|
+
|0.13.0|0.4.131|
|
|
48
47
|
|0.12.8|0.4.45|
|
|
48
|
+
|0.12.5|0.4.20|
|
|
49
|
+
|0.11.3|0.3.160|
|
|
49
50
|
|
|
50
51
|
|
|
51
52
|
## Installation
|
|
@@ -78,7 +79,7 @@ For Kwirth plugin to be usable on the frontend, you must tailor your Entity Page
|
|
|
78
79
|
```
|
|
79
80
|
|
|
80
81
|
Then, add a tab to your EntityPage (the 'if' is optional, you can keep the 'KwirthLog' tab always visible if you prefer to do it that way).
|
|
81
|
-
|
|
82
|
+
```jsx
|
|
82
83
|
// Note: Add to any other Pages as well (e.g. defaultEntityPage or webSiteEntityPage, for example)
|
|
83
84
|
const serviceEntityPage = (
|
|
84
85
|
<EntityLayout>
|
|
@@ -90,13 +91,30 @@ For Kwirth plugin to be usable on the frontend, you must tailor your Entity Page
|
|
|
90
91
|
)
|
|
91
92
|
```
|
|
92
93
|
|
|
94
|
+
You can setup some default *viewing* options on the `EntityKwirthLogContent` component, so, when the entity loads the default options will be set. These options are:
|
|
95
|
+
- `formStart`
|
|
96
|
+
- `showNames`
|
|
97
|
+
- `showTimestamp`
|
|
98
|
+
- `followLog`
|
|
99
|
+
- `wrapLines`
|
|
100
|
+
(The meaning of these properties are explained at the end of this document)
|
|
101
|
+
|
|
102
|
+
For example, you could setup your default log stream like this:
|
|
103
|
+
```jsx
|
|
104
|
+
...
|
|
105
|
+
<EntityLayout.Route if={isKwirthAvailable} path="/kwirthlog" title="KwirthLog">
|
|
106
|
+
<EntityKwirthLogContent enableRestart={false} fromStrat={true} showTimestamp={true} wrapLines={true} />
|
|
107
|
+
</EntityLayout.Route>
|
|
108
|
+
...
|
|
109
|
+
```
|
|
110
|
+
|
|
93
111
|
2. Label your catalog-info according to one of these two startegies:
|
|
94
112
|
|
|
95
113
|
- **Strategy 1: one-to-one**. Add `backstage.io/kubernetes-id` annotation to your `catalog-info.yaml` for the entities deployed to Kubernetes you want to work with on Backstage. This is the same annotation that the Kubernetes core plugin uses, so, maybe you already have added it to your components. Exmaple:
|
|
96
114
|
|
|
97
115
|
```yaml
|
|
98
116
|
metadata:
|
|
99
|
-
|
|
117
|
+
annotations:
|
|
100
118
|
backstage.io/kubernetes-id: entity001
|
|
101
119
|
```
|
|
102
120
|
|
|
@@ -166,6 +184,13 @@ Now you will see your log refreshing in real-time. If you selected more than one
|
|
|
166
184
|
|
|
167
185
|

|
|
168
186
|
|
|
187
|
+
### Filtering
|
|
188
|
+
When the log stream starts you will see a filter text field you can use for filtering messages. The use is as follows:
|
|
189
|
+
- If you type something, the messages (or the pod names or the container names) are expected to match that text.
|
|
190
|
+
- If you select `Aa`, the text match will be performed taking **casing** into account.
|
|
191
|
+
- If you select `.*` then the text entered will be treated as a regular expression.
|
|
192
|
+
- You can select *casing* and *regex* if you want regexes to match taking casing into account.
|
|
193
|
+
|
|
169
194
|
Feel free to open issues and ask for more features.
|
|
170
195
|
|
|
171
196
|
## Status information
|
|
@@ -182,3 +207,21 @@ This is how it feels:
|
|
|
182
207
|
|
|
183
208
|
If you click on one of the status icons when theyr are enableds (coloured), you will see the detail of the status.
|
|
184
209
|

|
|
210
|
+
|
|
211
|
+
## Log stream options
|
|
212
|
+
The log streaming system implemented in KwirthLog has some configuration options whose meaning is explained below.
|
|
213
|
+
|
|
214
|
+
### From start (`fromStart`)
|
|
215
|
+
If checked, the log streams will be retieved since pod start time. Please be careful with this option, it may impact your browser performance.
|
|
216
|
+
|
|
217
|
+
### Show message time (`showTimestamp`)
|
|
218
|
+
Decide whether to show timestamps next to messages or not. Usually your application logs messages with timestamp, but it this doesn't occur you can add message time (as provided by Kubernetes) to your messages.
|
|
219
|
+
|
|
220
|
+
### Show pod names (`showNames`)
|
|
221
|
+
Show pod names and container names next to messages. You may need to use this option if you are showing messages from different sources.
|
|
222
|
+
|
|
223
|
+
### Follow log stream (`followLog`)
|
|
224
|
+
If you activate this option, the log stream wil move to the end wehn a new messages arrives (it's like a `tail -f`).
|
|
225
|
+
|
|
226
|
+
### Wrap log lines (`wrapLines`)
|
|
227
|
+
Normally, KwirthLog will add hotizontal and vertical scrollers as needed in order to preserve original log lines, but you can activate this option to wrap lines and not to show horizontal scroller.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getVersion, getResources, requestAccess } from '@jfvilas/plugin-kwirth-common';
|
|
1
|
+
import { getVersion, getInfo, getResources, requestAccess } from '@jfvilas/plugin-kwirth-common';
|
|
2
2
|
|
|
3
3
|
class KwirthLogClient {
|
|
4
4
|
discoveryApi;
|
|
@@ -12,70 +12,18 @@ class KwirthLogClient {
|
|
|
12
12
|
* @param entity
|
|
13
13
|
* @returns an array of clusters (with their correpsonding info) and a pod list for each, where the entity has been dicovered
|
|
14
14
|
*/
|
|
15
|
-
// +++ test
|
|
16
15
|
async getVersion() {
|
|
17
16
|
return getVersion(this.discoveryApi, this.fetchApi);
|
|
18
17
|
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
// const targetUrl = `${baseUrl}/version`
|
|
23
|
-
// const result = await this.fetchApi.fetch(targetUrl)
|
|
24
|
-
// const data = await result.json()
|
|
25
|
-
// if (!result.ok) {
|
|
26
|
-
// throw new Error(`getVersion error: not ok`)
|
|
27
|
-
// }
|
|
28
|
-
// return data.version
|
|
29
|
-
// }
|
|
30
|
-
// catch (err) {
|
|
31
|
-
// throw new Error(`getVersion error: ${err}`)
|
|
32
|
-
// }
|
|
33
|
-
// }
|
|
34
|
-
// move to common
|
|
35
|
-
// async getResources(entity:Entity): Promise<ClusterValidPods> {
|
|
36
|
-
// try {
|
|
37
|
-
// const baseUrl = await this.discoveryApi.getBaseUrl('kwirth')
|
|
38
|
-
// const targetUrl = `${baseUrl}/start`
|
|
39
|
-
// var payload=JSON.stringify(entity)
|
|
40
|
-
// const result = await this.fetchApi.fetch(targetUrl, {method:'POST', body:payload, headers:{'Content-Type':'application/json'}})
|
|
41
|
-
// const data = await result.json() as ClusterValidPods
|
|
42
|
-
// if (!result.ok) {
|
|
43
|
-
// throw new Error(`getResources error: not ok`)
|
|
44
|
-
// }
|
|
45
|
-
// return data
|
|
46
|
-
// }
|
|
47
|
-
// catch (err) {
|
|
48
|
-
// throw new Error(`getResources error: ${err}`)
|
|
49
|
-
// }
|
|
50
|
-
// }
|
|
18
|
+
async getInfo() {
|
|
19
|
+
return getInfo(this.discoveryApi, this.fetchApi);
|
|
20
|
+
}
|
|
51
21
|
async getResources(entity) {
|
|
52
22
|
return getResources(this.discoveryApi, this.fetchApi, entity);
|
|
53
23
|
}
|
|
54
24
|
async requestAccess(entity, channel, scopes) {
|
|
55
25
|
return requestAccess(this.discoveryApi, this.fetchApi, entity, channel, scopes);
|
|
56
26
|
}
|
|
57
|
-
// async requestAccess(entity:Entity, channel:string, scopes:InstanceConfigScopeEnum[]): Promise<ClusterValidPods[]> {
|
|
58
|
-
// try {
|
|
59
|
-
// const baseUrl = await this.discoveryApi.getBaseUrl('kwirth')
|
|
60
|
-
// var targetUrl:URL= new URL (`${baseUrl}/access`)
|
|
61
|
-
// targetUrl.searchParams.append('scopes',scopes.join(','))
|
|
62
|
-
// targetUrl.searchParams.append('channel',channel)
|
|
63
|
-
// var payload=JSON.stringify(entity)
|
|
64
|
-
// const result = await this.fetchApi.fetch(targetUrl, {method:'POST', body:payload, headers:{'Content-Type':'application/json'}})
|
|
65
|
-
// const data = await result.json() as ClusterValidPods[]
|
|
66
|
-
// // we reconstruct the 'Map' from string of arrays
|
|
67
|
-
// for (var c of data) {
|
|
68
|
-
// c.accessKeys = new Map(JSON.parse(((c as any).accessKeys)))
|
|
69
|
-
// }
|
|
70
|
-
// if (!result.ok) {
|
|
71
|
-
// throw new Error(`requestAccess error: not ok`)
|
|
72
|
-
// }
|
|
73
|
-
// return data
|
|
74
|
-
// }
|
|
75
|
-
// catch (err) {
|
|
76
|
-
// throw new Error(`requestAccess error: ${err}`)
|
|
77
|
-
// }
|
|
78
|
-
// }
|
|
79
27
|
}
|
|
80
28
|
|
|
81
29
|
export { KwirthLogClient };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"KwirthLogClient.esm.js","sources":["../../src/api/KwirthLogClient.ts"],"sourcesContent":["/*\r\nCopyright 2024 Julio Fernandez\r\n\r\nLicensed under the Apache License, Version 2.0 (the \"License\");\r\nyou may not use this file except in compliance with the License.\r\nYou may obtain a copy of the License at\r\n\r\n http://www.apache.org/licenses/LICENSE-2.0\r\n\r\nUnless required by applicable law or agreed to in writing, software\r\ndistributed under the License is distributed on an \"AS IS\" BASIS,\r\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\nSee the License for the specific language governing permissions and\r\nlimitations under the License.\r\n*/\r\nimport { DiscoveryApi, FetchApi } from '@backstage/core-plugin-api'\r\nimport { KwirthLogApi } from './types'\r\nimport { Entity } from '@backstage/catalog-model'\r\nimport { ClusterValidPods, getResources, getVersion, requestAccess } from '@jfvilas/plugin-kwirth-common'\r\nimport { InstanceConfigScopeEnum } from '@jfvilas/kwirth-common'\r\n\r\nexport interface KwirthLogClientOptions {\r\n discoveryApi: DiscoveryApi\r\n fetchApi: FetchApi\r\n}\r\n\r\nexport class KwirthLogClient implements KwirthLogApi {\r\n private readonly discoveryApi: DiscoveryApi\r\n private readonly fetchApi: FetchApi\r\n\r\n constructor(options: KwirthLogClientOptions) {\r\n this.discoveryApi = options.discoveryApi\r\n this.fetchApi = options.fetchApi\r\n }\r\n\r\n /**\r\n * \r\n * @param entity \r\n * @returns an array of clusters (with their correpsonding info) and a pod list for each, where the entity has been dicovered\r\n */\r\n
|
|
1
|
+
{"version":3,"file":"KwirthLogClient.esm.js","sources":["../../src/api/KwirthLogClient.ts"],"sourcesContent":["/*\r\nCopyright 2024 Julio Fernandez\r\n\r\nLicensed under the Apache License, Version 2.0 (the \"License\");\r\nyou may not use this file except in compliance with the License.\r\nYou may obtain a copy of the License at\r\n\r\n http://www.apache.org/licenses/LICENSE-2.0\r\n\r\nUnless required by applicable law or agreed to in writing, software\r\ndistributed under the License is distributed on an \"AS IS\" BASIS,\r\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\nSee the License for the specific language governing permissions and\r\nlimitations under the License.\r\n*/\r\nimport { DiscoveryApi, FetchApi } from '@backstage/core-plugin-api'\r\nimport { KwirthLogApi } from './types'\r\nimport { Entity } from '@backstage/catalog-model'\r\nimport { ClusterValidPods, getInfo, getResources, getVersion, IBackendInfo, requestAccess } from '@jfvilas/plugin-kwirth-common'\r\nimport { InstanceConfigScopeEnum } from '@jfvilas/kwirth-common'\r\n\r\nexport interface KwirthLogClientOptions {\r\n discoveryApi: DiscoveryApi\r\n fetchApi: FetchApi\r\n}\r\n\r\nexport class KwirthLogClient implements KwirthLogApi {\r\n private readonly discoveryApi: DiscoveryApi\r\n private readonly fetchApi: FetchApi\r\n\r\n constructor(options: KwirthLogClientOptions) {\r\n this.discoveryApi = options.discoveryApi\r\n this.fetchApi = options.fetchApi\r\n }\r\n\r\n /**\r\n * \r\n * @param entity \r\n * @returns an array of clusters (with their correpsonding info) and a pod list for each, where the entity has been dicovered\r\n */\r\n async getVersion() : Promise<string> {\r\n return getVersion(this.discoveryApi, this.fetchApi)\r\n }\r\n\r\n async getInfo() : Promise<IBackendInfo> {\r\n return getInfo(this.discoveryApi, this.fetchApi)\r\n }\r\n\r\n async getResources(entity:Entity): Promise<ClusterValidPods> {\r\n return getResources(this.discoveryApi, this.fetchApi, entity)\r\n }\r\n\r\n async requestAccess(entity:Entity, channel:string, scopes:InstanceConfigScopeEnum[]): Promise<ClusterValidPods[]> {\r\n return requestAccess(this.discoveryApi, this.fetchApi, entity, channel, scopes)\r\n }\r\n\r\n}\r\n"],"names":[],"mappings":";;AA0BO,MAAM,eAAA,CAAwC;AAAA,EAChC,YAAA;AAAA,EACA,QAAA;AAAA,EAEjB,YAAY,OAAA,EAAiC;AACzC,IAAA,IAAA,CAAK,eAAe,OAAA,CAAQ,YAAA;AAC5B,IAAA,IAAA,CAAK,WAAW,OAAA,CAAQ,QAAA;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,UAAA,GAA+B;AACjC,IAAA,OAAO,UAAA,CAAW,IAAA,CAAK,YAAA,EAAc,IAAA,CAAK,QAAQ,CAAA;AAAA,EACtD;AAAA,EAEA,MAAM,OAAA,GAAkC;AACpC,IAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,YAAA,EAAc,IAAA,CAAK,QAAQ,CAAA;AAAA,EACnD;AAAA,EAEA,MAAM,aAAa,MAAA,EAA0C;AACzD,IAAA,OAAO,YAAA,CAAa,IAAA,CAAK,YAAA,EAAc,IAAA,CAAK,UAAU,MAAM,CAAA;AAAA,EAChE;AAAA,EAEA,MAAM,aAAA,CAAc,MAAA,EAAe,OAAA,EAAgB,MAAA,EAA+D;AAC9G,IAAA,OAAO,cAAc,IAAA,CAAK,YAAA,EAAc,KAAK,QAAA,EAAU,MAAA,EAAQ,SAAS,MAAM,CAAA;AAAA,EAClF;AAEJ;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.esm.js","sources":["../../src/api/types.ts"],"sourcesContent":["/*\r\nCopyright 2024 Julio Fernandez\r\n\r\nLicensed under the Apache License, Version 2.0 (the \"License\");\r\nyou may not use this file except in compliance with the License.\r\nYou may obtain a copy of the License at\r\n\r\n http://www.apache.org/licenses/LICENSE-2.0\r\n\r\nUnless required by applicable law or agreed to in writing, software\r\ndistributed under the License is distributed on an \"AS IS\" BASIS,\r\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\nSee the License for the specific language governing permissions and\r\nlimitations under the License.\r\n*/\r\nimport { Entity } from '@backstage/catalog-model'\r\nimport { createApiRef } from '@backstage/core-plugin-api'\r\nimport { InstanceConfigScopeEnum } from '@jfvilas/kwirth-common'\r\nimport { ClusterValidPods } from '@jfvilas/plugin-kwirth-common'\r\n\r\nexport interface KwirthLogApi {\r\n getResources(entity:Entity): Promise<any>\r\n requestAccess(entity:Entity, channel:string, scopes:InstanceConfigScopeEnum[]): Promise<ClusterValidPods[]>\r\n getVersion(): Promise<any>\r\n}\r\n\r\nexport const kwirthLogApiRef = createApiRef<KwirthLogApi>({\r\n id: 'plugin.kwirthlog.api',\r\n})\r\n"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"types.esm.js","sources":["../../src/api/types.ts"],"sourcesContent":["/*\r\nCopyright 2024 Julio Fernandez\r\n\r\nLicensed under the Apache License, Version 2.0 (the \"License\");\r\nyou may not use this file except in compliance with the License.\r\nYou may obtain a copy of the License at\r\n\r\n http://www.apache.org/licenses/LICENSE-2.0\r\n\r\nUnless required by applicable law or agreed to in writing, software\r\ndistributed under the License is distributed on an \"AS IS\" BASIS,\r\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\nSee the License for the specific language governing permissions and\r\nlimitations under the License.\r\n*/\r\nimport { Entity } from '@backstage/catalog-model'\r\nimport { createApiRef } from '@backstage/core-plugin-api'\r\nimport { InstanceConfigScopeEnum } from '@jfvilas/kwirth-common'\r\nimport { ClusterValidPods } from '@jfvilas/plugin-kwirth-common'\r\n\r\nexport interface KwirthLogApi {\r\n getResources(entity:Entity): Promise<any>\r\n requestAccess(entity:Entity, channel:string, scopes:InstanceConfigScopeEnum[]): Promise<ClusterValidPods[]>\r\n getVersion(): Promise<any>\r\n getInfo(): any\r\n}\r\n\r\nexport const kwirthLogApiRef = createApiRef<KwirthLogApi>({\r\n id: 'plugin.kwirthlog.api',\r\n})\r\n"],"names":[],"mappings":";;AA2BO,MAAM,kBAAkB,YAAA,CAA2B;AAAA,EACxD,EAAA,EAAI;AACN,CAAC;;;;"}
|
|
@@ -2,16 +2,13 @@ import React, { useState, useRef } from 'react';
|
|
|
2
2
|
import useAsync from 'react-use/esm/useAsync';
|
|
3
3
|
import { Progress, WarningPanel } from '@backstage/core-components';
|
|
4
4
|
import { useApi, alertApiRef } from '@backstage/core-plugin-api';
|
|
5
|
-
import { isKwirthAvailable, ANNOTATION_BACKSTAGE_KUBERNETES_LABELID, ANNOTATION_BACKSTAGE_KUBERNETES_LABELSELECTOR } from '@jfvilas/plugin-kwirth-common';
|
|
5
|
+
import { isKwirthAvailable, ANNOTATION_BACKSTAGE_KUBERNETES_LABELID, ANNOTATION_BACKSTAGE_KUBERNETES_LABELSELECTOR, getPodList, getContainerList } from '@jfvilas/plugin-kwirth-common';
|
|
6
6
|
import { useEntity, MissingAnnotationEmptyState } from '@backstage/plugin-catalog-react';
|
|
7
|
-
import { kwirthLogApiRef } from '
|
|
7
|
+
import { kwirthLogApiRef } from '../api/types.esm.js';
|
|
8
8
|
import { SignalMessageLevelEnum, InstanceConfigScopeEnum, InstanceMessageChannelEnum, InstanceMessageTypeEnum, OpsCommandEnum, accessKeySerialize, InstanceMessageFlowEnum, InstanceMessageActionEnum, InstanceConfigViewEnum, InstanceConfigObjectEnum } from '@jfvilas/kwirth-common';
|
|
9
|
-
import {
|
|
10
|
-
import { ObjectSelector } from '
|
|
11
|
-
import {
|
|
12
|
-
import { ClusterList } from '../ClusterList/ClusterList.esm.js';
|
|
13
|
-
import { StatusLog } from '../StatusLog/StatusLog.esm.js';
|
|
14
|
-
import { Box, Grid, Card, CardHeader, CardContent } from '@material-ui/core';
|
|
9
|
+
import { Options } from './Options.esm.js';
|
|
10
|
+
import { ComponentNotFound, ErrorType, ClusterList, KwirthNews, ObjectSelector, StatusLog } from '@jfvilas/plugin-kwirth-frontend';
|
|
11
|
+
import { Box, Grid, Card, CardHeader, TextField, InputAdornment, CardContent } from '@material-ui/core';
|
|
15
12
|
import Divider from '@material-ui/core/Divider';
|
|
16
13
|
import IconButton from '@material-ui/core/IconButton';
|
|
17
14
|
import Typography from '@material-ui/core/Typography';
|
|
@@ -22,7 +19,7 @@ import InfoIcon from '@material-ui/icons/Info';
|
|
|
22
19
|
import WarningIcon from '@material-ui/icons/Warning';
|
|
23
20
|
import ErrorIcon from '@material-ui/icons/Error';
|
|
24
21
|
import DownloadIcon from '@material-ui/icons/CloudDownload';
|
|
25
|
-
import KwirthLogLogo from '
|
|
22
|
+
import KwirthLogLogo from '../assets/kwirthlog-logo.svg';
|
|
26
23
|
import RefreshIcon from '@material-ui/icons/Refresh';
|
|
27
24
|
|
|
28
25
|
const LOG_MAX_MESSAGES = 1e3;
|
|
@@ -30,7 +27,7 @@ const EntityKwirthLogContent = (props) => {
|
|
|
30
27
|
const { entity } = useEntity();
|
|
31
28
|
const kwirthLogApi = useApi(kwirthLogApiRef);
|
|
32
29
|
const alertApi = useApi(alertApiRef);
|
|
33
|
-
const [
|
|
30
|
+
const [validClusters, setResources] = useState([]);
|
|
34
31
|
const [selectedClusterName, setSelectedClusterName] = useState("");
|
|
35
32
|
const [selectedNamespaces, setSelectedNamespaces] = useState([]);
|
|
36
33
|
const [selectedPodNames, setSelectedPodNames] = useState([]);
|
|
@@ -43,20 +40,33 @@ const EntityKwirthLogContent = (props) => {
|
|
|
43
40
|
const [statusMessages, setStatusMessages] = useState([]);
|
|
44
41
|
const [websocket, setWebsocket] = useState();
|
|
45
42
|
const [instance, setInstance] = useState();
|
|
46
|
-
const kwirthLogOptionsRef = useRef({
|
|
43
|
+
const kwirthLogOptionsRef = useRef({
|
|
44
|
+
fromStart: props.fromStart !== void 0 ? props.fromStart : false,
|
|
45
|
+
showTimestamp: props.showTimestamp !== void 0 ? props.showTimestamp : false,
|
|
46
|
+
showNames: props.showNames !== void 0 ? props.showNames : true,
|
|
47
|
+
followLog: props.followLog !== void 0 ? props.followLog : true,
|
|
48
|
+
wrapLines: props.wrapLines !== void 0 ? props.wrapLines : false
|
|
49
|
+
});
|
|
47
50
|
const [showStatusDialog, setShowStatusDialog] = useState(false);
|
|
48
51
|
const [statusLevel, setStatusLevel] = useState(SignalMessageLevelEnum.INFO);
|
|
49
52
|
const preRef = useRef(null);
|
|
50
53
|
const lastRef = useRef(null);
|
|
51
54
|
const [backendVersion, setBackendVersion] = useState("");
|
|
55
|
+
const [backendInfo, setBackendInfo] = useState();
|
|
52
56
|
const { loading, error } = useAsync(async () => {
|
|
53
57
|
if (backendVersion === "") setBackendVersion(await kwirthLogApi.getVersion());
|
|
58
|
+
if (!backendInfo) setBackendInfo(await kwirthLogApi.getInfo());
|
|
54
59
|
let reqScopes = [InstanceConfigScopeEnum.VIEW];
|
|
55
60
|
if (props.enableRestart) reqScopes.push(InstanceConfigScopeEnum.RESTART);
|
|
56
61
|
let data = await kwirthLogApi.requestAccess(entity, InstanceMessageChannelEnum.LOG, reqScopes);
|
|
57
62
|
setResources(data);
|
|
58
63
|
});
|
|
59
64
|
const buffer = useRef(/* @__PURE__ */ new Map());
|
|
65
|
+
const [filter, setFilter] = useState("");
|
|
66
|
+
const [filterCasing, setFilterCasing] = useState(false);
|
|
67
|
+
const [filterRegex, setFilterRegex] = useState(false);
|
|
68
|
+
const adornmentSelected = { margin: 0, borderWidth: 1, borderStyle: "solid", borderColor: "gray", paddingLeft: 3, paddingRight: 3, backgroundColor: "gray", cursor: "pointer", color: "white" };
|
|
69
|
+
const adornmentNotSelected = { margin: 0, borderWidth: 1, borderStyle: "solid", borderColor: "#f0f0f0", backgroundColor: "#f0f0f0", paddingLeft: 3, paddingRight: 3, cursor: "pointer" };
|
|
60
70
|
const clickStart = (options) => {
|
|
61
71
|
if (!paused.current) {
|
|
62
72
|
setStarted(true);
|
|
@@ -80,21 +90,32 @@ const EntityKwirthLogContent = (props) => {
|
|
|
80
90
|
paused.current = false;
|
|
81
91
|
stopLogViewer();
|
|
82
92
|
};
|
|
83
|
-
const onSelectCluster = (
|
|
84
|
-
if (
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
type: InstanceMessageTypeEnum.SIGNAL,
|
|
88
|
-
text: "Select namespace in order to decide which pod logs to view.",
|
|
89
|
-
namespace: "",
|
|
90
|
-
pod: "",
|
|
91
|
-
container: ""
|
|
92
|
-
}]);
|
|
93
|
-
setSelectedNamespaces([]);
|
|
93
|
+
const onSelectCluster = (clusterName) => {
|
|
94
|
+
if (started) onClickStop();
|
|
95
|
+
if (clusterName) {
|
|
96
|
+
setSelectedClusterName(clusterName);
|
|
94
97
|
setSelectedPodNames([]);
|
|
95
98
|
setSelectedContainerNames([]);
|
|
96
99
|
setStatusMessages([]);
|
|
97
|
-
|
|
100
|
+
let cluster = validClusters.find((cluster2) => cluster2.name === clusterName);
|
|
101
|
+
if (cluster && cluster.pods) {
|
|
102
|
+
let validNamespaces = Array.from(new Set(cluster.pods.map((pod) => pod.namespace)));
|
|
103
|
+
if (validNamespaces.length === 1) {
|
|
104
|
+
setSelectedNamespaces(validNamespaces);
|
|
105
|
+
let podList = getPodList(cluster.pods, validNamespaces);
|
|
106
|
+
setSelectedPodNames(podList.map((pod) => pod.name));
|
|
107
|
+
setSelectedContainerNames(getContainerList(cluster.pods, validNamespaces, podList.map((pod) => pod.name)));
|
|
108
|
+
} else {
|
|
109
|
+
setMessages([{
|
|
110
|
+
type: InstanceMessageTypeEnum.SIGNAL,
|
|
111
|
+
text: "Select namespace in order to decide which pod logs to view.",
|
|
112
|
+
namespace: "",
|
|
113
|
+
pod: "",
|
|
114
|
+
container: ""
|
|
115
|
+
}]);
|
|
116
|
+
setSelectedNamespaces([]);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
98
119
|
}
|
|
99
120
|
};
|
|
100
121
|
const processLogMessage = (wsEvent) => {
|
|
@@ -130,7 +151,7 @@ const EntityKwirthLogContent = (props) => {
|
|
|
130
151
|
while (prev.length > LOG_MAX_MESSAGES - 1) {
|
|
131
152
|
prev.splice(0, 1);
|
|
132
153
|
}
|
|
133
|
-
if (kwirthLogOptionsRef.current.
|
|
154
|
+
if (kwirthLogOptionsRef.current.followLog && lastRef.current) lastRef.current.scrollIntoView({ behavior: "instant", block: "start" });
|
|
134
155
|
return [...prev, logLine];
|
|
135
156
|
});
|
|
136
157
|
}
|
|
@@ -142,24 +163,28 @@ const EntityKwirthLogContent = (props) => {
|
|
|
142
163
|
setInstance(instanceMessage.instance);
|
|
143
164
|
else {
|
|
144
165
|
let signalMessage = instanceMessage;
|
|
145
|
-
|
|
166
|
+
if (signalMessage.text) {
|
|
167
|
+
alertApi.post({ message: signalMessage.text, severity: "error", display: "transient" });
|
|
168
|
+
}
|
|
146
169
|
}
|
|
147
170
|
} else {
|
|
148
171
|
let signalMessage = instanceMessage;
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
172
|
+
if (signalMessage.text) {
|
|
173
|
+
addMessage(signalMessage.level, signalMessage.text);
|
|
174
|
+
switch (signalMessage.level) {
|
|
175
|
+
case SignalMessageLevelEnum.INFO:
|
|
176
|
+
alertApi.post({ message: signalMessage.text, severity: "info", display: "transient" });
|
|
177
|
+
break;
|
|
178
|
+
case SignalMessageLevelEnum.WARNING:
|
|
179
|
+
alertApi.post({ message: signalMessage.text, severity: "warning", display: "transient" });
|
|
180
|
+
break;
|
|
181
|
+
case SignalMessageLevelEnum.ERROR:
|
|
182
|
+
alertApi.post({ message: signalMessage.text, severity: "error", display: "transient" });
|
|
183
|
+
break;
|
|
184
|
+
default:
|
|
185
|
+
alertApi.post({ message: signalMessage.text, severity: "success", display: "transient" });
|
|
186
|
+
break;
|
|
187
|
+
}
|
|
163
188
|
}
|
|
164
189
|
}
|
|
165
190
|
break;
|
|
@@ -203,12 +228,12 @@ const EntityKwirthLogContent = (props) => {
|
|
|
203
228
|
}
|
|
204
229
|
};
|
|
205
230
|
const websocketOnOpen = (ws, options) => {
|
|
206
|
-
let cluster =
|
|
231
|
+
let cluster = validClusters.find((cluster2) => cluster2.name === selectedClusterName);
|
|
207
232
|
if (!cluster) {
|
|
208
233
|
addMessage(SignalMessageLevelEnum.ERROR, "No cluster selected");
|
|
209
234
|
return;
|
|
210
235
|
}
|
|
211
|
-
let pods = cluster.
|
|
236
|
+
let pods = cluster.pods.filter((p2) => selectedNamespaces.includes(p2.namespace));
|
|
212
237
|
if (!pods) {
|
|
213
238
|
addMessage(SignalMessageLevelEnum.ERROR, "No pods found");
|
|
214
239
|
return;
|
|
@@ -238,7 +263,7 @@ const EntityKwirthLogContent = (props) => {
|
|
|
238
263
|
pod: selectedPodNames.map((p2) => p2).join(","),
|
|
239
264
|
container: containers.join(","),
|
|
240
265
|
data: {
|
|
241
|
-
timestamp: options.
|
|
266
|
+
timestamp: options.showTimestamp,
|
|
242
267
|
previous: false,
|
|
243
268
|
maxMessages: LOG_MAX_MESSAGES,
|
|
244
269
|
fromStart: options.fromStart
|
|
@@ -252,7 +277,7 @@ const EntityKwirthLogContent = (props) => {
|
|
|
252
277
|
}
|
|
253
278
|
};
|
|
254
279
|
const startLogViewer = (options) => {
|
|
255
|
-
let cluster =
|
|
280
|
+
let cluster = validClusters.find((cluster2) => cluster2.name === selectedClusterName);
|
|
256
281
|
if (!cluster) {
|
|
257
282
|
addMessage(SignalMessageLevelEnum.ERROR, "No cluster selected");
|
|
258
283
|
return;
|
|
@@ -314,7 +339,7 @@ const EntityKwirthLogContent = (props) => {
|
|
|
314
339
|
URL.revokeObjectURL(url);
|
|
315
340
|
};
|
|
316
341
|
const onClickRestart = () => {
|
|
317
|
-
var cluster =
|
|
342
|
+
var cluster = validClusters.find((cluster2) => cluster2.name === selectedClusterName);
|
|
318
343
|
if (!cluster) {
|
|
319
344
|
addMessage(SignalMessageLevelEnum.ERROR, "No cluster selected");
|
|
320
345
|
return;
|
|
@@ -328,7 +353,7 @@ const EntityKwirthLogContent = (props) => {
|
|
|
328
353
|
addMessage(SignalMessageLevelEnum.ERROR, "No instance has been established");
|
|
329
354
|
return;
|
|
330
355
|
}
|
|
331
|
-
let pods = cluster.
|
|
356
|
+
let pods = cluster.pods.filter((pod) => selectedNamespaces.includes(pod.namespace));
|
|
332
357
|
for (let pod of pods) {
|
|
333
358
|
let opsMessage = {
|
|
334
359
|
msgtype: "opsmessage",
|
|
@@ -361,7 +386,7 @@ const EntityKwirthLogContent = (props) => {
|
|
|
361
386
|
};
|
|
362
387
|
const actionButtons = () => {
|
|
363
388
|
let hasViewKey = false, hasRestartKey = false;
|
|
364
|
-
let cluster =
|
|
389
|
+
let cluster = validClusters.find((cluster2) => cluster2.name === selectedClusterName);
|
|
365
390
|
if (cluster) {
|
|
366
391
|
hasViewKey = Boolean(cluster.accessKeys.get(InstanceConfigScopeEnum.VIEW));
|
|
367
392
|
hasRestartKey = Boolean(cluster.accessKeys.get(InstanceConfigScopeEnum.RESTART));
|
|
@@ -373,7 +398,10 @@ const EntityKwirthLogContent = (props) => {
|
|
|
373
398
|
setShowStatusDialog(true);
|
|
374
399
|
setStatusLevel(level);
|
|
375
400
|
};
|
|
376
|
-
|
|
401
|
+
const prepareText = (txt) => {
|
|
402
|
+
return txt ? txt.length > 25 ? txt.substring(0, 25) + "..." : txt : "N/A";
|
|
403
|
+
};
|
|
404
|
+
return /* @__PURE__ */ React.createElement(Grid, { container: true, direction: "row" }, /* @__PURE__ */ React.createElement(Grid, { item: true }, /* @__PURE__ */ React.createElement(Typography, { variant: "h5" }, prepareText(title))), /* @__PURE__ */ React.createElement(Grid, { item: true, style: { marginTop: "-8px" } }, /* @__PURE__ */ React.createElement(IconButton, { title: "info", disabled: !statusMessages.some((m) => m.type === InstanceMessageTypeEnum.SIGNAL && m.level === SignalMessageLevelEnum.INFO), onClick: () => show(SignalMessageLevelEnum.INFO) }, /* @__PURE__ */ React.createElement(InfoIcon, { style: { color: statusMessages.some((m) => m.type === InstanceMessageTypeEnum.SIGNAL && m.level === SignalMessageLevelEnum.INFO) ? "blue" : "#BDBDBD" } })), /* @__PURE__ */ React.createElement(IconButton, { title: "warning", disabled: !statusMessages.some((m) => m.type === InstanceMessageTypeEnum.SIGNAL && m.level === SignalMessageLevelEnum.WARNING), onClick: () => show(SignalMessageLevelEnum.WARNING), style: { marginLeft: "-16px" } }, /* @__PURE__ */ React.createElement(WarningIcon, { style: { color: statusMessages.some((m) => m.type === InstanceMessageTypeEnum.SIGNAL && m.level === SignalMessageLevelEnum.WARNING) ? "orange" : "#BDBDBD" } })), /* @__PURE__ */ React.createElement(IconButton, { title: "error", disabled: !statusMessages.some((m) => m.type === InstanceMessageTypeEnum.SIGNAL && m.level === SignalMessageLevelEnum.ERROR), onClick: () => show(SignalMessageLevelEnum.ERROR), style: { marginLeft: "-16px" } }, /* @__PURE__ */ React.createElement(ErrorIcon, { style: { color: statusMessages.some((m) => m.type === InstanceMessageTypeEnum.SIGNAL && m.level === SignalMessageLevelEnum.ERROR) ? "red" : "#BDBDBD" } }))));
|
|
377
405
|
};
|
|
378
406
|
const statusClear = (level) => {
|
|
379
407
|
setStatusMessages(statusMessages.filter((m) => m.level !== level));
|
|
@@ -384,12 +412,40 @@ const EntityKwirthLogContent = (props) => {
|
|
|
384
412
|
setSelectedPodNames(podNames);
|
|
385
413
|
setSelectedContainerNames(containerNames);
|
|
386
414
|
};
|
|
415
|
+
const onChangeFilter = (event) => {
|
|
416
|
+
setFilter(event.target?.value);
|
|
417
|
+
};
|
|
387
418
|
const formatMessage = (logLine) => {
|
|
388
419
|
if (!logLine.pod) {
|
|
389
420
|
return /* @__PURE__ */ React.createElement(React.Fragment, null, logLine.text + "\n");
|
|
390
421
|
}
|
|
422
|
+
if (filter !== "") {
|
|
423
|
+
if (filterCasing) {
|
|
424
|
+
if (filterRegex) {
|
|
425
|
+
try {
|
|
426
|
+
const regex = new RegExp(filter);
|
|
427
|
+
if (!regex.test(logLine.text) && !regex.test(logLine.pod) && !regex.test(logLine.container)) return /* @__PURE__ */ React.createElement(React.Fragment, null);
|
|
428
|
+
} catch {
|
|
429
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null);
|
|
430
|
+
}
|
|
431
|
+
} else {
|
|
432
|
+
if (!logLine.text.includes(filter) && !logLine.pod.includes(filter) && !logLine.container.includes(filter)) return /* @__PURE__ */ React.createElement(React.Fragment, null);
|
|
433
|
+
}
|
|
434
|
+
} else {
|
|
435
|
+
if (filterRegex) {
|
|
436
|
+
try {
|
|
437
|
+
const regex = new RegExp(filter.toLocaleLowerCase());
|
|
438
|
+
if (!regex.test(logLine.text.toLocaleLowerCase()) && !regex.test(logLine.pod.toLocaleLowerCase()) && !regex.test(logLine.container.toLocaleLowerCase())) return /* @__PURE__ */ React.createElement(React.Fragment, null);
|
|
439
|
+
} catch {
|
|
440
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null);
|
|
441
|
+
}
|
|
442
|
+
} else {
|
|
443
|
+
if (!logLine.text.toLocaleLowerCase().includes(filter.toLowerCase()) && !logLine.pod.toLocaleLowerCase().includes(filter.toLocaleLowerCase()) && !logLine.container.toLocaleLowerCase().includes(filter.toLocaleLowerCase())) return /* @__PURE__ */ React.createElement(React.Fragment, null);
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
}
|
|
391
447
|
let podPrefix = /* @__PURE__ */ React.createElement(React.Fragment, null);
|
|
392
|
-
if (selectedPodNames.length !== 1) {
|
|
448
|
+
if (selectedPodNames.length !== 1 || kwirthLogOptionsRef.current.showNames) {
|
|
393
449
|
podPrefix = /* @__PURE__ */ React.createElement("span", { style: { color: "green" } }, logLine.pod + " ");
|
|
394
450
|
}
|
|
395
451
|
let containerPrefix = /* @__PURE__ */ React.createElement(React.Fragment, null);
|
|
@@ -398,14 +454,27 @@ const EntityKwirthLogContent = (props) => {
|
|
|
398
454
|
}
|
|
399
455
|
return /* @__PURE__ */ React.createElement(React.Fragment, null, podPrefix, containerPrefix, logLine.text + "\n");
|
|
400
456
|
};
|
|
401
|
-
return /* @__PURE__ */ React.createElement(React.Fragment, null, loading && /* @__PURE__ */ React.createElement(Progress, null), !isKwirthAvailable(entity) && !loading && error && /* @__PURE__ */ React.createElement(WarningPanel, { title: "An error has ocurred while obtaining data from kuebernetes clusters.", message: error?.message }), !isKwirthAvailable(entity) && !loading && /* @__PURE__ */ React.createElement(MissingAnnotationEmptyState, { readMoreUrl: "https://github.com/jfvilas/plugin-kwirth-log", annotation: [ANNOTATION_BACKSTAGE_KUBERNETES_LABELID, ANNOTATION_BACKSTAGE_KUBERNETES_LABELSELECTOR] }), isKwirthAvailable(entity) && !loading &&
|
|
457
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, loading && /* @__PURE__ */ React.createElement(Progress, null), !isKwirthAvailable(entity) && !loading && error && /* @__PURE__ */ React.createElement(WarningPanel, { title: "An error has ocurred while obtaining data from kuebernetes clusters.", message: error?.message }), !isKwirthAvailable(entity) && !loading && /* @__PURE__ */ React.createElement(MissingAnnotationEmptyState, { readMoreUrl: "https://github.com/jfvilas/plugin-kwirth-log", annotation: [ANNOTATION_BACKSTAGE_KUBERNETES_LABELID, ANNOTATION_BACKSTAGE_KUBERNETES_LABELSELECTOR] }), isKwirthAvailable(entity) && !loading && validClusters && validClusters.length === 0 && /* @__PURE__ */ React.createElement(ComponentNotFound, { error: ErrorType.NO_CLUSTERS, entity }), isKwirthAvailable(entity) && !loading && validClusters && validClusters.length > 0 && validClusters.reduce((sum, cluster) => sum + cluster.pods.length, 0) === 0 && /* @__PURE__ */ React.createElement(ComponentNotFound, { error: ErrorType.NO_PODS, entity }), isKwirthAvailable(entity) && !loading && validClusters && validClusters.length > 0 && validClusters.reduce((sum, cluster) => sum + cluster.pods.length, 0) > 0 && /* @__PURE__ */ React.createElement(Box, { sx: { display: "flex", height: "70vh" } }, /* @__PURE__ */ React.createElement(Box, { sx: { width: "200px", maxWidth: "200px" } }, /* @__PURE__ */ React.createElement(Grid, { container: true, direction: "column" }, /* @__PURE__ */ React.createElement(Grid, { item: true }, /* @__PURE__ */ React.createElement(Card, null, /* @__PURE__ */ React.createElement(ClusterList, { resources: validClusters, selectedClusterName, onSelect: onSelectCluster }))), /* @__PURE__ */ React.createElement(Grid, { item: true }, /* @__PURE__ */ React.createElement(Card, null, /* @__PURE__ */ React.createElement(Options, { options: kwirthLogOptionsRef.current, onChange: onChangeLogConfig, disabled: selectedContainerNames.length === 0 || started || paused.current }))), /* @__PURE__ */ React.createElement(Grid, { item: true }, /* @__PURE__ */ React.createElement(Card, null, /* @__PURE__ */ React.createElement(KwirthNews, { latestVersions: backendInfo, backendVersion }))))), /* @__PURE__ */ React.createElement(Box, { sx: { flexGrow: 1, flex: 1, overflow: "hidden", p: 1, marginLeft: "8px" } }, !selectedClusterName && /* @__PURE__ */ React.createElement("img", { src: KwirthLogLogo, alt: "No cluster selected", style: { left: "40%", marginTop: "10%", width: "20%", position: "relative" } }), selectedClusterName && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Card, { style: { marginTop: -8, height: "100%", display: "flex", flexDirection: "column" } }, /* @__PURE__ */ React.createElement(
|
|
402
458
|
CardHeader,
|
|
403
459
|
{
|
|
404
460
|
title: statusButtons(selectedClusterName),
|
|
405
461
|
style: { marginTop: -4, marginBottom: 4, flexShrink: 0 },
|
|
406
462
|
action: actionButtons()
|
|
407
463
|
}
|
|
408
|
-
), /* @__PURE__ */ React.createElement(
|
|
464
|
+
), /* @__PURE__ */ React.createElement(Grid, { container: true, style: { alignItems: "end" } }, /* @__PURE__ */ React.createElement(Grid, { item: true, style: { width: "66%" } }, /* @__PURE__ */ React.createElement(Typography, { style: { marginLeft: 14 } }, /* @__PURE__ */ React.createElement(ObjectSelector, { cluster: validClusters.find((cluster) => cluster.name === selectedClusterName), onSelect: onSelectObject, disabled: selectedClusterName === "" || started || paused.current, selectedNamespaces, selectedPodNames, selectedContainerNames, scope: InstanceConfigScopeEnum.VIEW }))), /* @__PURE__ */ React.createElement(Grid, { item: true, style: { width: "33%", marginLeft: 0 } }, /* @__PURE__ */ React.createElement(
|
|
465
|
+
TextField,
|
|
466
|
+
{
|
|
467
|
+
value: filter,
|
|
468
|
+
onChange: onChangeFilter,
|
|
469
|
+
label: "Filter",
|
|
470
|
+
fullWidth: true,
|
|
471
|
+
style: { marginBottom: 6, marginLeft: 0 },
|
|
472
|
+
disabled: !started,
|
|
473
|
+
InputProps: {
|
|
474
|
+
endAdornment: /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(InputAdornment, { position: "start", onClick: () => started && setFilterRegex(!filterRegex), style: { margin: 0 } }, /* @__PURE__ */ React.createElement(Typography, { style: filterRegex ? adornmentSelected : adornmentNotSelected }, ".*")), /* @__PURE__ */ React.createElement(InputAdornment, { position: "start", onClick: () => started && setFilterCasing(!filterCasing), style: { margin: 0, marginLeft: 1 } }, /* @__PURE__ */ React.createElement(Typography, { style: filterCasing ? adornmentSelected : adornmentNotSelected }, "Aa")))
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
))), /* @__PURE__ */ React.createElement(Divider, null), /* @__PURE__ */ React.createElement(CardContent, { style: { flexGrow: 1, overflow: "hidden", display: "flex", flexDirection: "column" } }, /* @__PURE__ */ React.createElement(Box, { style: { overflowY: "auto", width: "100%", flexGrow: 1 } }, /* @__PURE__ */ React.createElement("pre", { ref: preRef, style: { overflowX: kwirthLogOptionsRef.current.wrapLines ? "hidden" : "auto", whiteSpace: kwirthLogOptionsRef.current.wrapLines ? "pre-wrap" : "pre", wordBreak: kwirthLogOptionsRef.current.wrapLines ? "break-word" : "normal" } }, messages.map((m) => formatMessage(m))), /* @__PURE__ */ React.createElement("span", { ref: lastRef }))))))), showStatusDialog && /* @__PURE__ */ React.createElement(StatusLog, { level: statusLevel, onClose: () => setShowStatusDialog(false), statusMessages, onClear: statusClear }));
|
|
409
478
|
};
|
|
410
479
|
|
|
411
480
|
export { EntityKwirthLogContent };
|