@jfvilas/plugin-kwirth-log 0.12.4 → 0.12.6

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 CHANGED
@@ -1,9 +1,12 @@
1
1
  # Backstage frontend KwirthLog plugin
2
- This package is a Backstage plugin for **viewing Kubernetes logs** in real-time (live-streaming) via Kwirth.
2
+ This package is a Backstage frontend plugin for **viewing Kubernetes logs** in real-time (live-streaming) via Kwirth.
3
3
 
4
- **NOTE: KwithLog requires Kwirth vesrsion 0.3.155 or greater**
4
+ **NOTE: KwithLog requires Kwirth vesrsion 0.3.160 or greater**
5
5
 
6
- This Backstage plugin allows you to live-stream Kubernetes logs associated to your Backstage entities directly inside your Backstage instance. It's very important to understand that for this plugin to work you need to install Kwirth on your Kubernetes cluster, that is, this plugin is just another front end for [Kwirth](https://jfvilas.github.io/kwirth).
6
+ This Backstage plugin allows you to live-stream Kubernetes logs associated to your Backstage entities directly inside your Backstage instance. It's very important to understand that for this plugin to work...:
7
+
8
+ - You need to install the Kwirth [Backstage backend plugin](https://www.npmjs.com/package/@jfvilas/plugin-kwirth-backend).
9
+ - You need to install Kwirth on your Kubernetes cluster, that is, this plugin is just another frontend for [Kwirth](https://jfvilas.github.io/kwirth).
7
10
 
8
11
  Kwirth is a really-easy-to-use data-exporting system for Kubernetes that runs in only one pod (*no database is needed*). Refer to Kwirth GitHub project for [info on installation](https://github.com/jfvilas/kwirth?tab=readme-ov-file#installation). Kwirth installation is *one command away* from you.
9
12
 
@@ -11,7 +14,7 @@ You can access [Kwirth project here](https://github.com/jfvilas/kwirth).
11
14
 
12
15
 
13
16
  ## What is this plugin for?
14
- This Backstage plugin adds Backstage a feature for viewing real-time Kubernetes logs of your Backstage entities directly inside Backstage frontend application. The plugin will be enabled for any entity that is corectly tagged (according to Backstage Kubernetes core feature) and its correpsonding Kubernetes resources are found on any of the clusters that have been added to Backstage.
17
+ This Backstage plugin adds Backstage a feature for viewing real-time Kubernetes logs of your Backstage entities directly inside Backstage frontend application. The plugin will be enabled for any entity that is correctly tagged (according to Backstage Kubernetes core feature) and its correpsonding Kubernetes resources are found on any of the clusters that have been added to Backstage.
15
18
 
16
19
  When KwirthLog is correctly installed and configured, it is possible to view Kubernetes logs on your Backstage like in this sample:
17
20
 
@@ -33,6 +36,15 @@ Let's explain this by following a user working sequence:
33
36
  If everyting is correctly configured and tagged, the user should see a list of clusters. When selecting a cluster, the user should see a list of namespaces where the entity is running.
34
37
 
35
38
 
39
+ ## Version compatibility
40
+ Following table shows version compatibility between this Kwirth Backstage plugin and Kwirth Core server.
41
+
42
+ | Plugin Kwirth version | Kwirth version |
43
+ |-|-|
44
+ |0.11.3|0.3.155|
45
+ |0.12.5|0.4.20|
46
+
47
+
36
48
  ## Installation
37
49
  It's very simple and straightforward, it is in fact very similar to any other forntend Backstage plugin.
38
50
 
@@ -40,9 +52,9 @@ It's very simple and straightforward, it is in fact very similar to any other fo
40
52
 
41
53
  2. Install this Backstage frontend plugin:
42
54
 
43
- ```bash
55
+ ```sh
44
56
  # From your Backstage root directory
45
- yarn --cwd packages/app add @jfvilas/plugin-kwirth-log @jfvilas/plugin-kwirth-common
57
+ yarn --cwd packages/app add @jfvilas/plugin-kwirth-log @jfvilas/plugin-kwirth-common @jfvilas/kwirth-common
46
58
  ```
47
59
 
48
60
  3. Make sure the [Kwirth backend plugin](https://www.npmjs.com/package/@jfvilas/plugin-kwirth-backend#configure) is installed and configured.
@@ -69,7 +81,7 @@ For Kwirth plugin to be usable on the frontend, you must tailor your Entity Page
69
81
  <EntityLayout>
70
82
  {/* other tabs... */}
71
83
  <EntityLayout.Route if={isKwirthAvailable} path="/kwirthlog" title="KwirthLog">
72
- <EntityKwirthLogContent />
84
+ <EntityKwirthLogContent enableRestart={false} />
73
85
  </EntityLayout.Route>
74
86
  </EntityLayout>
75
87
  )
@@ -1,3 +1,5 @@
1
+ import { getVersion, requestAccess } from '@jfvilas/plugin-kwirth-common';
2
+
1
3
  class KwirthLogClient {
2
4
  discoveryApi;
3
5
  fetchApi;
@@ -10,20 +12,25 @@ class KwirthLogClient {
10
12
  * @param entity
11
13
  * @returns an array of clusters (with their correpsonding info) and a pod list for each, where the entity has been dicovered
12
14
  */
15
+ // +++ test
13
16
  async getVersion() {
14
- try {
15
- const baseUrl = await this.discoveryApi.getBaseUrl("kwirth");
16
- const targetUrl = `${baseUrl}/version`;
17
- const result = await this.fetchApi.fetch(targetUrl);
18
- const data = await result.json();
19
- if (!result.ok) {
20
- throw new Error(`getVersion error: not ok`);
21
- }
22
- return data.version;
23
- } catch (err) {
24
- throw new Error(`getVersion error: ${err}`);
25
- }
17
+ return getVersion(this.discoveryApi, this.fetchApi);
26
18
  }
19
+ // async getVersion(): Promise<string> {
20
+ // try {
21
+ // const baseUrl = await this.discoveryApi.getBaseUrl('kwirth')
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
+ // }
27
34
  async getResources(entity) {
28
35
  try {
29
36
  const baseUrl = await this.discoveryApi.getBaseUrl("kwirth");
@@ -40,25 +47,30 @@ class KwirthLogClient {
40
47
  }
41
48
  }
42
49
  async requestAccess(entity, channel, scopes) {
43
- try {
44
- const baseUrl = await this.discoveryApi.getBaseUrl("kwirth");
45
- var targetUrl = new URL(`${baseUrl}/access`);
46
- targetUrl.searchParams.append("scopes", scopes.join(","));
47
- targetUrl.searchParams.append("channel", channel);
48
- var payload = JSON.stringify(entity);
49
- const result = await this.fetchApi.fetch(targetUrl, { method: "POST", body: payload, headers: { "Content-Type": "application/json" } });
50
- const data = await result.json();
51
- for (var c of data) {
52
- c.accessKeys = new Map(JSON.parse(c.accessKeys));
53
- }
54
- if (!result.ok) {
55
- throw new Error(`requestAccess error: not ok`);
56
- }
57
- return data;
58
- } catch (err) {
59
- throw new Error(`requestAccess error: ${err}`);
60
- }
50
+ return requestAccess(this.discoveryApi, this.fetchApi, entity, channel, scopes);
61
51
  }
52
+ // async requestAccess(entity:Entity, channel:string, scopes:InstanceConfigScopeEnum[]): Promise<ClusterValidPods[]> {
53
+ // try {
54
+ // const baseUrl = await this.discoveryApi.getBaseUrl('kwirth')
55
+ // var targetUrl:URL= new URL (`${baseUrl}/access`)
56
+ // targetUrl.searchParams.append('scopes',scopes.join(','))
57
+ // targetUrl.searchParams.append('channel',channel)
58
+ // var payload=JSON.stringify(entity)
59
+ // const result = await this.fetchApi.fetch(targetUrl, {method:'POST', body:payload, headers:{'Content-Type':'application/json'}})
60
+ // const data = await result.json() as ClusterValidPods[]
61
+ // // we reconstruct the 'Map' from string of arrays
62
+ // for (var c of data) {
63
+ // c.accessKeys = new Map(JSON.parse(((c as any).accessKeys)))
64
+ // }
65
+ // if (!result.ok) {
66
+ // throw new Error(`requestAccess error: not ok`)
67
+ // }
68
+ // return data
69
+ // }
70
+ // catch (err) {
71
+ // throw new Error(`requestAccess error: ${err}`)
72
+ // }
73
+ // }
62
74
  }
63
75
 
64
76
  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 } 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 try {\r\n const baseUrl = await this.discoveryApi.getBaseUrl('kwirth')\r\n const targetUrl = `${baseUrl}/version`\r\n\r\n const result = await this.fetchApi.fetch(targetUrl)\r\n const data = await result.json()\r\n\r\n if (!result.ok) {\r\n throw new Error(`getVersion error: not ok`)\r\n }\r\n return data.version\r\n }\r\n catch (err) {\r\n throw new Error(`getVersion error: ${err}`)\r\n }\r\n }\r\n\r\n async getResources(entity:Entity): Promise<ClusterValidPods> {\r\n try {\r\n const baseUrl = await this.discoveryApi.getBaseUrl('kwirth')\r\n const targetUrl = `${baseUrl}/start`\r\n\r\n var payload=JSON.stringify(entity)\r\n const result = await this.fetchApi.fetch(targetUrl, {method:'POST', body:payload, headers:{'Content-Type':'application/json'}})\r\n const data = await result.json() as ClusterValidPods\r\n\r\n if (!result.ok) {\r\n throw new Error(`getResources error: not ok`)\r\n }\r\n return data\r\n }\r\n catch (err) {\r\n throw new Error(`getResources error: ${err}`)\r\n }\r\n }\r\n\r\n async requestAccess(entity:Entity, channel:string, scopes:InstanceConfigScopeEnum[]): Promise<ClusterValidPods[]> {\r\n try {\r\n const baseUrl = await this.discoveryApi.getBaseUrl('kwirth')\r\n var targetUrl:URL= new URL (`${baseUrl}/access`)\r\n targetUrl.searchParams.append('scopes',scopes.join(',')) //+++ poner mas elegante\r\n targetUrl.searchParams.append('channel',channel)\r\n\r\n var payload=JSON.stringify(entity)\r\n const result = await this.fetchApi.fetch(targetUrl, {method:'POST', body:payload, headers:{'Content-Type':'application/json'}})\r\n const data = await result.json() as ClusterValidPods[]\r\n\r\n // we reconstruct the 'Map' from string of arrays\r\n for (var c of data) {\r\n c.accessKeys = new Map(JSON.parse(((c as any).accessKeys)))\r\n }\r\n if (!result.ok) {\r\n throw new Error(`requestAccess error: not ok`)\r\n }\r\n return data\r\n }\r\n catch (err) {\r\n throw new Error(`requestAccess error: ${err}`)\r\n }\r\n }\r\n\r\n}\r\n"],"names":[],"mappings":"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"}
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, 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 // +++ test\r\n async getVersion() : Promise<string> {\r\n return getVersion(this.discoveryApi, this.fetchApi)\r\n }\r\n // async getVersion(): Promise<string> {\r\n // try {\r\n // const baseUrl = await this.discoveryApi.getBaseUrl('kwirth')\r\n // const targetUrl = `${baseUrl}/version`\r\n\r\n // const result = await this.fetchApi.fetch(targetUrl)\r\n // const data = await result.json()\r\n\r\n // if (!result.ok) {\r\n // throw new Error(`getVersion error: not ok`)\r\n // }\r\n // return data.version\r\n // }\r\n // catch (err) {\r\n // throw new Error(`getVersion error: ${err}`)\r\n // }\r\n // }\r\n\r\n async getResources(entity:Entity): Promise<ClusterValidPods> {\r\n try {\r\n const baseUrl = await this.discoveryApi.getBaseUrl('kwirth')\r\n const targetUrl = `${baseUrl}/start`\r\n\r\n var payload=JSON.stringify(entity)\r\n const result = await this.fetchApi.fetch(targetUrl, {method:'POST', body:payload, headers:{'Content-Type':'application/json'}})\r\n const data = await result.json() as ClusterValidPods\r\n\r\n if (!result.ok) {\r\n throw new Error(`getResources error: not ok`)\r\n }\r\n return data\r\n }\r\n catch (err) {\r\n throw new Error(`getResources error: ${err}`)\r\n }\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 // async requestAccess(entity:Entity, channel:string, scopes:InstanceConfigScopeEnum[]): Promise<ClusterValidPods[]> {\r\n // try {\r\n // const baseUrl = await this.discoveryApi.getBaseUrl('kwirth')\r\n // var targetUrl:URL= new URL (`${baseUrl}/access`)\r\n // targetUrl.searchParams.append('scopes',scopes.join(','))\r\n // targetUrl.searchParams.append('channel',channel)\r\n\r\n // var payload=JSON.stringify(entity)\r\n // const result = await this.fetchApi.fetch(targetUrl, {method:'POST', body:payload, headers:{'Content-Type':'application/json'}})\r\n // const data = await result.json() as ClusterValidPods[]\r\n\r\n // // we reconstruct the 'Map' from string of arrays\r\n // for (var c of data) {\r\n // c.accessKeys = new Map(JSON.parse(((c as any).accessKeys)))\r\n // }\r\n // if (!result.ok) {\r\n // throw new Error(`requestAccess error: not ok`)\r\n // }\r\n // return data\r\n // }\r\n // catch (err) {\r\n // throw new Error(`requestAccess error: ${err}`)\r\n // }\r\n // }\r\n\r\n}\r\n"],"names":[],"mappings":";;AA0BO,MAAM,eAAwC,CAAA;AAAA,EAChC,YAAA;AAAA,EACA,QAAA;AAAA,EAEjB,YAAY,OAAiC,EAAA;AACzC,IAAA,IAAA,CAAK,eAAe,OAAQ,CAAA,YAAA;AAC5B,IAAA,IAAA,CAAK,WAAW,OAAQ,CAAA,QAAA;AAAA;AAC5B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,UAA+B,GAAA;AACjC,IAAA,OAAO,UAAW,CAAA,IAAA,CAAK,YAAc,EAAA,IAAA,CAAK,QAAQ,CAAA;AAAA;AACtD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmBA,MAAM,aAAa,MAA0C,EAAA;AACzD,IAAI,IAAA;AACA,MAAA,MAAM,OAAU,GAAA,MAAM,IAAK,CAAA,YAAA,CAAa,WAAW,QAAQ,CAAA;AAC3D,MAAM,MAAA,SAAA,GAAY,GAAG,OAAO,CAAA,MAAA,CAAA;AAE5B,MAAI,IAAA,OAAA,GAAQ,IAAK,CAAA,SAAA,CAAU,MAAM,CAAA;AACjC,MAAA,MAAM,SAAS,MAAM,IAAA,CAAK,QAAS,CAAA,KAAA,CAAM,WAAW,EAAC,MAAA,EAAO,MAAQ,EAAA,IAAA,EAAK,SAAS,OAAQ,EAAA,EAAC,cAAe,EAAA,kBAAA,IAAoB,CAAA;AAC9H,MAAM,MAAA,IAAA,GAAO,MAAM,MAAA,CAAO,IAAK,EAAA;AAE/B,MAAI,IAAA,CAAC,OAAO,EAAI,EAAA;AACZ,QAAM,MAAA,IAAI,MAAM,CAA4B,0BAAA,CAAA,CAAA;AAAA;AAEhD,MAAO,OAAA,IAAA;AAAA,aAEJ,GAAK,EAAA;AACR,MAAA,MAAM,IAAI,KAAA,CAAM,CAAuB,oBAAA,EAAA,GAAG,CAAE,CAAA,CAAA;AAAA;AAChD;AACJ,EAEA,MAAM,aAAA,CAAc,MAAe,EAAA,OAAA,EAAgB,MAA+D,EAAA;AAC9G,IAAA,OAAO,cAAc,IAAK,CAAA,YAAA,EAAc,KAAK,QAAU,EAAA,MAAA,EAAQ,SAAS,MAAM,CAAA;AAAA;AAClF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA2BJ;;;;"}
@@ -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, scopes:string[]): 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":";;AA2BO,MAAM,kBAAkB,YAA2B,CAAA;AAAA,EACxD,EAAI,EAAA;AACN,CAAC;;;;"}
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":";;AA0BO,MAAM,kBAAkB,YAA2B,CAAA;AAAA,EACxD,EAAI,EAAA;AACN,CAAC;;;;"}
@@ -11,8 +11,8 @@
11
11
  <rect style="fill-rule: nonzero; stroke: rgb(255, 255, 255); stroke-width: 0px; fill: rgb(230, 230, 230); transform-origin: 228.554px 205.227px;" transform="matrix(0.985765, -0.168131, 0.16314, 0.986616, -50.714188, -2.839044)" x="101.002" y="192.327" width="255.103" height="25.801" rx="12.015" ry="12.015"></rect>
12
12
  <rect style="fill-rule: nonzero; stroke: rgb(255, 255, 255); stroke-width: 0px; fill: rgb(230, 230, 230); transform-origin: 231.862px 205.227px;" transform="matrix(0.985765, -0.168131, 0.16314, 0.986616, -73.522724, -49.884953)" x="102.464" y="192.327" width="258.794" height="25.801" rx="12.015" ry="12.015"></rect>
13
13
  <path style="color: rgb(0, 0, 0); font-style: normal; font-variant: normal; font-weight: normal; font-stretch: normal; font-size: medium; line-height: normal; font-family: sans-serif; font-feature-settings: normal; text-indent: 0px; text-align: start; text-decoration: none solid rgb(0, 0, 0); letter-spacing: normal; word-spacing: normal; text-transform: none; writing-mode: lr-tb; direction: ltr; text-orientation: mixed; dominant-baseline: auto; baseline-shift: baseline; text-anchor: start; white-space: normal; clip-rule: nonzero; display: inline; overflow: visible; visibility: visible; opacity: 1; isolation: auto; mix-blend-mode: normal; color-interpolation: srgb; color-interpolation-filters: linearrgb; vector-effect: none; fill: rgb(255, 255, 255); fill-opacity: 1; fill-rule: evenodd; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 4; stroke-dasharray: none; stroke-dashoffset: 0; stroke-opacity: 1; color-rendering: auto; image-rendering: auto; shape-rendering: auto; text-rendering: auto; paint-order: fill; stroke-width: 9px; stroke: rgb(74, 74, 74);" d="M 90.279 31.639 L 236.352 31.639 L 236.352 225.458 L 90.279 225.458 L 90.279 31.639 Z" id="path3310"></path>
14
- <g id="g3330" transform="matrix(0.441209, 0, 0, 0.468545, -799.76062, -5194.109863)">
15
- <g transform="matrix(6.103682, 0, 0, 5.928513, 1904.565796, 10952.352539)">
14
+ <g id="g3330" transform="matrix(0.417521, 0, 0, 0.461789, -751.809143, -5115.862305)" style="">
15
+ <g transform="matrix(6.103682, 0, 0, 5.605206, 1904.565796, 10976.322266)" style="">
16
16
  <g>
17
17
  <path d="M 68.066 63.636 L 25.648 63.636 C 25.096 63.636 24.648 63.189 24.648 62.636 C 24.648 62.083 25.096 61.636 25.648 61.636 L 68.066 61.636 C 68.619 61.636 69.066 62.083 69.066 62.636 C 69.066 63.189 68.619 63.636 68.066 63.636 Z" style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill-rule: nonzero; opacity: 1; fill: rgb(156, 156, 156);" stroke-linecap="round"></path>
18
18
  <path d="M 54.048 57.677 L 25.325 57.677 C 24.951 57.677 24.648 57.23 24.648 56.677 C 24.648 56.124 24.951 55.677 25.325 55.677 L 54.048 55.677 C 54.422 55.677 54.725 56.124 54.725 56.677 C 54.725 57.23 54.422 57.677 54.048 57.677 Z" style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill-rule: nonzero; opacity: 1; fill: rgb(156, 156, 156);" stroke-linecap="round"></path>
@@ -26,5 +26,5 @@
26
26
  </g>
27
27
  </g>
28
28
  </g>
29
- <text style="fill: rgb(74, 74, 74); font-family: Consolas; font-size: 34px; font-weight: 700; stroke-miterlimit: 10; stroke-width: 0px; white-space: pre;" transform="matrix(0.654152, 0, 0, 0.636825, 32.884773, 81.612808)" x="114.293" y="147.365">KwirthLog</text>
29
+ <text style="fill: rgb(74, 74, 74); font-family: Consolas; font-size: 34px; font-weight: 700; stroke-miterlimit: 10; stroke-width: 0px; white-space: pre;" transform="matrix(0.654152, 0, 0, 0.636825, 31.813269, 80.181999)" x="114.293" y="147.365">KwirthLog</text>
30
30
  </svg>
@@ -1,7 +1,7 @@
1
1
  <svg viewBox="0 0 152 200" xmlns="http://www.w3.org/2000/svg" xmlns:bx="https://boxy-svg.com">
2
2
  <path style="color: rgb(0, 0, 0); font-style: normal; font-variant: normal; font-weight: normal; font-stretch: normal; font-size: medium; line-height: normal; font-family: sans-serif; font-feature-settings: normal; text-indent: 0px; text-align: start; text-decoration: none solid rgb(0, 0, 0); letter-spacing: normal; word-spacing: normal; text-transform: none; writing-mode: lr-tb; direction: ltr; text-orientation: mixed; dominant-baseline: auto; baseline-shift: baseline; text-anchor: start; white-space: normal; clip-rule: nonzero; display: inline; overflow: visible; visibility: visible; opacity: 1; isolation: auto; mix-blend-mode: normal; color-interpolation: srgb; color-interpolation-filters: linearrgb; vector-effect: none; fill: rgb(255, 255, 255); fill-opacity: 1; fill-rule: evenodd; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 4; stroke-dasharray: none; stroke-dashoffset: 0; stroke-opacity: 1; color-rendering: auto; image-rendering: auto; shape-rendering: auto; text-rendering: auto; paint-order: fill; stroke-width: 9px; stroke: rgb(74, 74, 74);" d="M 3.001 3.226 L 149.074 3.226 L 149.074 197.045 L 3.001 197.045 L 3.001 3.226 Z" id="path3310"></path>
3
- <g id="g3330" transform="matrix(0.441209, 0, 0, 0.468545, -887.038696, -5222.522461)">
4
- <g transform="matrix(6.103682, 0, 0, 5.928513, 1904.565796, 10952.352539)">
3
+ <g id="g3330" transform="matrix(0.417521, 0, 0, 0.461789, -838.360535, -5144.637207)" style="">
4
+ <g transform="matrix(6.103682, 0, 0, 5.605206, 1904.565796, 10976.322266)" style="">
5
5
  <g>
6
6
  <path d="M 68.066 63.636 L 25.648 63.636 C 25.096 63.636 24.648 63.189 24.648 62.636 C 24.648 62.083 25.096 61.636 25.648 61.636 L 68.066 61.636 C 68.619 61.636 69.066 62.083 69.066 62.636 C 69.066 63.189 68.619 63.636 68.066 63.636 Z" style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill-rule: nonzero; opacity: 1; fill: rgb(156, 156, 156);" stroke-linecap="round"></path>
7
7
  <path d="M 54.048 57.677 L 25.325 57.677 C 24.951 57.677 24.648 57.23 24.648 56.677 C 24.648 56.124 24.951 55.677 25.325 55.677 L 54.048 55.677 C 54.422 55.677 54.725 56.124 54.725 56.677 C 54.725 57.23 54.422 57.677 54.048 57.677 Z" style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill-rule: nonzero; opacity: 1; fill: rgb(156, 156, 156);" stroke-linecap="round"></path>
@@ -15,5 +15,5 @@
15
15
  </g>
16
16
  </g>
17
17
  </g>
18
- <text style="fill: rgb(74, 74, 74); font-family: Consolas; font-size: 34px; font-weight: 700; stroke-miterlimit: 10; stroke-width: 0px; white-space: pre;" transform="matrix(0.654152, 0, 0, 0.636825, -54.393276, 53.200108)" x="114.293" y="147.365">KwirthLog</text>
18
+ <text style="fill: rgb(74, 74, 74); font-family: Consolas; font-size: 34px; font-weight: 700; stroke-miterlimit: 10; stroke-width: 0px; white-space: pre;" transform="matrix(0.654152, 0, 0, 0.636825, -53.705204, 51.365246)" x="114.293" y="147.365">KwirthLog</text>
19
19
  </svg>
@@ -1,17 +1,17 @@
1
1
  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
- import { useApi } from '@backstage/core-plugin-api';
4
+ import { useApi, alertApiRef } from '@backstage/core-plugin-api';
5
5
  import { isKwirthAvailable, ANNOTATION_KWIRTH_LOCATION } from '@jfvilas/plugin-kwirth-common';
6
6
  import { useEntity, MissingAnnotationEmptyState } from '@backstage/plugin-catalog-react';
7
7
  import { kwirthLogApiRef } from '../../api/types.esm.js';
8
- import { SignalMessageLevelEnum, InstanceConfigScopeEnum, InstanceMessageTypeEnum, InstanceConfigChannelEnum, InstanceConfigViewEnum, accessKeySerialize, InstanceConfigFlowEnum, InstanceConfigActionEnum, InstanceConfigObjectEnum } from '@jfvilas/kwirth-common';
8
+ import { SignalMessageLevelEnum, InstanceConfigScopeEnum, InstanceMessageChannelEnum, InstanceMessageTypeEnum, OpsCommandEnum, accessKeySerialize, InstanceMessageFlowEnum, InstanceMessageActionEnum, InstanceConfigViewEnum, InstanceConfigObjectEnum } from '@jfvilas/kwirth-common';
9
9
  import { ComponentNotFound, ErrorType } from '../ComponentNotFound/ComponentNotFound.esm.js';
10
+ import { ObjectSelector } from '../ObjectSelector/ObjectSelector.esm.js';
10
11
  import { Options } from '../Options/Options.esm.js';
11
12
  import { ClusterList } from '../ClusterList/ClusterList.esm.js';
12
- import { ShowError } from '../ShowError/ShowError.esm.js';
13
13
  import { StatusLog } from '../StatusLog/StatusLog.esm.js';
14
- import { Grid, Card, CardHeader, CardContent } from '@material-ui/core';
14
+ import { Box, Grid, Card, CardHeader, CardContent } from '@material-ui/core';
15
15
  import Divider from '@material-ui/core/Divider';
16
16
  import IconButton from '@material-ui/core/IconButton';
17
17
  import Typography from '@material-ui/core/Typography';
@@ -23,19 +23,18 @@ import WarningIcon from '@material-ui/icons/Warning';
23
23
  import ErrorIcon from '@material-ui/icons/Error';
24
24
  import DownloadIcon from '@material-ui/icons/CloudDownload';
25
25
  import KwirthLogLogo from '../../assets/kwirthlog-logo.svg';
26
- import { ObjectSelector } from '../ObjectSelector/ObjectSelector.esm.js';
26
+ import RefreshIcon from '@material-ui/icons/Refresh';
27
27
 
28
28
  const LOG_MAX_MESSAGES = 1e3;
29
- const EntityKwirthLogContent = () => {
29
+ const EntityKwirthLogContent = (props) => {
30
30
  const { entity } = useEntity();
31
31
  const kwirthLogApi = useApi(kwirthLogApiRef);
32
+ const alertApi = useApi(alertApiRef);
32
33
  const [resources, setResources] = useState([]);
33
34
  const [selectedClusterName, setSelectedClusterName] = useState("");
34
- const [_namespaceList, setNamespaceList] = useState([]);
35
35
  const [selectedNamespaces, setSelectedNamespaces] = useState([]);
36
36
  const [selectedPodNames, setSelectedPodNames] = useState([]);
37
37
  const [selectedContainerNames, setSelectedContainerNames] = useState([]);
38
- const [showError, setShowError] = useState("");
39
38
  const [started, setStarted] = useState(false);
40
39
  const [stopped, setStopped] = useState(true);
41
40
  const paused = useRef(false);
@@ -43,6 +42,7 @@ const EntityKwirthLogContent = () => {
43
42
  const [pendingMessages, setPendingMessages] = useState([]);
44
43
  const [statusMessages, setStatusMessages] = useState([]);
45
44
  const [websocket, setWebsocket] = useState();
45
+ const [instance, setInstance] = useState();
46
46
  const kwirthLogOptionsRef = useRef({ timestamp: false, follow: true, fromStart: false });
47
47
  const [showStatusDialog, setShowStatusDialog] = useState(false);
48
48
  const [statusLevel, setStatusLevel] = useState(SignalMessageLevelEnum.INFO);
@@ -51,9 +51,12 @@ const EntityKwirthLogContent = () => {
51
51
  const [backendVersion, setBackendVersion] = useState("");
52
52
  const { loading, error } = useAsync(async () => {
53
53
  if (backendVersion === "") setBackendVersion(await kwirthLogApi.getVersion());
54
- var data = await kwirthLogApi.requestAccess(entity, "log", [InstanceConfigScopeEnum.VIEW, InstanceConfigScopeEnum.RESTART]);
54
+ let reqScopes = [InstanceConfigScopeEnum.VIEW];
55
+ if (props.enableRestart) reqScopes.push(InstanceConfigScopeEnum.RESTART);
56
+ let data = await kwirthLogApi.requestAccess(entity, InstanceMessageChannelEnum.LOG, reqScopes);
55
57
  setResources(data);
56
58
  });
59
+ const buffer = useRef(/* @__PURE__ */ new Map());
57
60
  const clickStart = (options) => {
58
61
  if (!paused.current) {
59
62
  setStarted(true);
@@ -67,11 +70,11 @@ const EntityKwirthLogContent = () => {
67
70
  setStarted(true);
68
71
  }
69
72
  };
70
- const clickPause = () => {
73
+ const onClickPause = () => {
71
74
  setStarted(false);
72
75
  paused.current = true;
73
76
  };
74
- const clickStop = () => {
77
+ const onClickStop = () => {
75
78
  setStarted(false);
76
79
  setStopped(true);
77
80
  paused.current = false;
@@ -80,57 +83,99 @@ const EntityKwirthLogContent = () => {
80
83
  const onSelectCluster = (name) => {
81
84
  if (name) {
82
85
  setSelectedClusterName(name);
83
- resources.filter((cluster) => cluster.name === name).map((x) => {
84
- var namespaces = Array.from(new Set(x.data.map((p) => p.namespace)));
85
- setNamespaceList(namespaces);
86
- });
87
86
  setMessages([{
88
- channel: InstanceConfigChannelEnum.LOG,
89
87
  type: InstanceMessageTypeEnum.SIGNAL,
90
88
  text: "Select namespace in order to decide which pod logs to view.",
91
- instance: ""
89
+ namespace: "",
90
+ pod: "",
91
+ container: ""
92
92
  }]);
93
93
  setSelectedNamespaces([]);
94
94
  setSelectedPodNames([]);
95
95
  setSelectedContainerNames([]);
96
96
  setStatusMessages([]);
97
- clickStop();
97
+ onClickStop();
98
98
  }
99
99
  };
100
100
  const processLogMessage = (wsEvent) => {
101
- let msg = JSON.parse(wsEvent.data);
102
- switch (msg.type) {
103
- case "data":
104
- var lmsg = msg;
105
- if (paused.current) {
106
- setPendingMessages((prev) => [...prev, lmsg]);
107
- } else {
108
- setMessages((prev) => {
109
- while (prev.length > LOG_MAX_MESSAGES - 1) {
110
- prev.splice(0, 1);
111
- }
112
- if (kwirthLogOptionsRef.current.follow && lastRef.current) lastRef.current.scrollIntoView({ behavior: "instant", block: "start" });
113
- return [...prev, lmsg];
114
- });
101
+ let instanceMessage = JSON.parse(wsEvent.data);
102
+ switch (instanceMessage.type) {
103
+ case InstanceMessageTypeEnum.DATA:
104
+ let logMessage = instanceMessage;
105
+ let bname = logMessage.namespace + "/" + logMessage.pod + "/" + logMessage.container;
106
+ let text = logMessage.text;
107
+ if (!buffer.current.has(bname)) buffer.current.set(bname, "");
108
+ if (buffer.current.get(bname)) {
109
+ text = buffer.current.get(bname) + text;
110
+ buffer.current.set(bname, "");
111
+ }
112
+ if (!text.endsWith("\n")) {
113
+ let i = text.lastIndexOf("\n");
114
+ buffer.current.set(bname, text.substring(i));
115
+ text = text.substring(0, i);
116
+ }
117
+ for (let line of text.split("\n")) {
118
+ if (line.trim() === "") continue;
119
+ let logLine = {
120
+ text: line,
121
+ namespace: logMessage.namespace,
122
+ pod: logMessage.pod,
123
+ container: logMessage.container,
124
+ type: logMessage.type
125
+ };
126
+ if (paused.current) {
127
+ setPendingMessages((prev) => [...prev, logLine]);
128
+ } else {
129
+ setMessages((prev) => {
130
+ while (prev.length > LOG_MAX_MESSAGES - 1) {
131
+ prev.splice(0, 1);
132
+ }
133
+ if (kwirthLogOptionsRef.current.follow && lastRef.current) lastRef.current.scrollIntoView({ behavior: "instant", block: "start" });
134
+ return [...prev, logLine];
135
+ });
136
+ }
115
137
  }
116
138
  break;
117
- case "signal":
118
- let smsg = msg;
119
- setStatusMessages((prev) => [...prev, smsg]);
139
+ case InstanceMessageTypeEnum.SIGNAL:
140
+ if (instanceMessage.flow === InstanceMessageFlowEnum.RESPONSE && instanceMessage.action === InstanceMessageActionEnum.START) {
141
+ if (instanceMessage.instance !== "")
142
+ setInstance(instanceMessage.instance);
143
+ else {
144
+ let signalMessage = instanceMessage;
145
+ alertApi.post({ message: signalMessage.text, severity: "error", display: "transient" });
146
+ }
147
+ } else {
148
+ let signalMessage = instanceMessage;
149
+ addMessage(signalMessage.level, signalMessage.text);
150
+ switch (signalMessage.level) {
151
+ case SignalMessageLevelEnum.INFO:
152
+ alertApi.post({ message: signalMessage.text, severity: "info", display: "transient" });
153
+ break;
154
+ case SignalMessageLevelEnum.WARNING:
155
+ alertApi.post({ message: signalMessage.text, severity: "warning", display: "transient" });
156
+ break;
157
+ case SignalMessageLevelEnum.ERROR:
158
+ alertApi.post({ message: signalMessage.text, severity: "error", display: "transient" });
159
+ break;
160
+ default:
161
+ alertApi.post({ message: signalMessage.text, severity: "success", display: "transient" });
162
+ break;
163
+ }
164
+ }
120
165
  break;
121
166
  default:
122
- console.log("Invalid message type:");
123
- console.log(msg);
124
- setStatusMessages((prev) => [...prev, {
125
- channel: InstanceConfigChannelEnum.LOG,
126
- type: InstanceMessageTypeEnum.SIGNAL,
127
- level: SignalMessageLevelEnum.ERROR,
128
- text: "Invalid message type received: " + msg.type,
129
- instance: ""
130
- }]);
167
+ addMessage(SignalMessageLevelEnum.ERROR, "Invalid message type received: " + instanceMessage.type);
168
+ alertApi.post({ message: "Invalid message type received: " + instanceMessage.type, severity: "error", display: "transient" });
131
169
  break;
132
170
  }
133
171
  };
172
+ const addMessage = (level, text) => {
173
+ setStatusMessages((prev) => [...prev, {
174
+ level,
175
+ text,
176
+ type: InstanceMessageTypeEnum.SIGNAL
177
+ }]);
178
+ };
134
179
  const websocketOnMessage = (wsEvent) => {
135
180
  let instanceMessage;
136
181
  try {
@@ -141,21 +186,31 @@ const EntityKwirthLogContent = () => {
141
186
  return;
142
187
  }
143
188
  switch (instanceMessage.channel) {
144
- case "log":
189
+ case InstanceMessageChannelEnum.LOG:
145
190
  processLogMessage(wsEvent);
146
191
  break;
192
+ case InstanceMessageChannelEnum.OPS:
193
+ let opsMessage = instanceMessage;
194
+ if (opsMessage.data?.data)
195
+ addMessage(SignalMessageLevelEnum.WARNING, "Operations message: " + opsMessage.data.data);
196
+ else
197
+ addMessage(SignalMessageLevelEnum.WARNING, "Operations message: " + JSON.stringify(opsMessage));
198
+ break;
147
199
  default:
148
- console.log("Invalid channel in message: ", instanceMessage);
200
+ addMessage(SignalMessageLevelEnum.ERROR, "Invalid channel in message: " + instanceMessage.channel);
201
+ addMessage(SignalMessageLevelEnum.ERROR, "Invalid message: " + JSON.stringify(instanceMessage));
149
202
  break;
150
203
  }
151
204
  };
152
205
  const websocketOnOpen = (ws, options) => {
153
206
  let cluster = resources.find((cluster2) => cluster2.name === selectedClusterName);
154
207
  if (!cluster) {
208
+ addMessage(SignalMessageLevelEnum.ERROR, "No cluster selected");
155
209
  return;
156
210
  }
157
211
  let pods = cluster.data.filter((p2) => selectedNamespaces.includes(p2.namespace));
158
212
  if (!pods) {
213
+ addMessage(SignalMessageLevelEnum.ERROR, "No pods found");
159
214
  return;
160
215
  }
161
216
  console.log(`WS connected`);
@@ -170,10 +225,10 @@ const EntityKwirthLogContent = () => {
170
225
  }
171
226
  }
172
227
  let iConfig = {
173
- channel: InstanceConfigChannelEnum.LOG,
228
+ channel: InstanceMessageChannelEnum.LOG,
174
229
  objects: InstanceConfigObjectEnum.PODS,
175
- action: InstanceConfigActionEnum.START,
176
- flow: InstanceConfigFlowEnum.REQUEST,
230
+ action: InstanceMessageActionEnum.START,
231
+ flow: InstanceMessageFlowEnum.REQUEST,
177
232
  instance: "",
178
233
  accessKey: accessKeySerialize(accessKey),
179
234
  scope: InstanceConfigScopeEnum.VIEW,
@@ -187,14 +242,19 @@ const EntityKwirthLogContent = () => {
187
242
  previous: false,
188
243
  maxMessages: LOG_MAX_MESSAGES,
189
244
  fromStart: options.fromStart
190
- }
245
+ },
246
+ type: InstanceMessageTypeEnum.SIGNAL
191
247
  };
192
248
  ws.send(JSON.stringify(iConfig));
249
+ } else {
250
+ addMessage(SignalMessageLevelEnum.ERROR, "No accessKey for starting log streaming");
251
+ return;
193
252
  }
194
253
  };
195
254
  const startLogViewer = (options) => {
196
255
  let cluster = resources.find((cluster2) => cluster2.name === selectedClusterName);
197
256
  if (!cluster) {
257
+ addMessage(SignalMessageLevelEnum.ERROR, "No cluster selected");
198
258
  return;
199
259
  }
200
260
  setMessages([]);
@@ -206,10 +266,11 @@ const EntityKwirthLogContent = () => {
206
266
  setWebsocket(ws);
207
267
  } catch (err) {
208
268
  setMessages([{
209
- channel: InstanceConfigChannelEnum.LOG,
210
269
  type: InstanceMessageTypeEnum.DATA,
211
270
  text: `Error opening log stream: ${err}`,
212
- instance: ""
271
+ namespace: "",
272
+ pod: "",
273
+ container: ""
213
274
  }]);
214
275
  }
215
276
  };
@@ -221,10 +282,11 @@ const EntityKwirthLogContent = () => {
221
282
  };
222
283
  const stopLogViewer = () => {
223
284
  messages.push({
224
- channel: InstanceConfigChannelEnum.LOG,
225
285
  type: InstanceMessageTypeEnum.DATA,
226
286
  text: "============================================================================================================================",
227
- instance: ""
287
+ namespace: "",
288
+ pod: "",
289
+ container: ""
228
290
  });
229
291
  websocket?.close();
230
292
  };
@@ -234,7 +296,7 @@ const EntityKwirthLogContent = () => {
234
296
  clickStart(options);
235
297
  }
236
298
  };
237
- const handleDownload = () => {
299
+ const onClickDownload = () => {
238
300
  let content = preRef.current.innerHTML.replaceAll("<pre>", "").replaceAll("</pre>", "\n");
239
301
  content = content.replaceAll('<span style="color: green;">', "");
240
302
  content = content.replaceAll('<span style="color: blue;">', "");
@@ -251,18 +313,67 @@ const EntityKwirthLogContent = () => {
251
313
  document.body.removeChild(link);
252
314
  URL.revokeObjectURL(url);
253
315
  };
316
+ const onClickRestart = () => {
317
+ var cluster = resources.find((cluster2) => cluster2.name === selectedClusterName);
318
+ if (!cluster) {
319
+ addMessage(SignalMessageLevelEnum.ERROR, "No cluster selected");
320
+ return;
321
+ }
322
+ let restartKey = cluster.accessKeys.get(InstanceConfigScopeEnum.RESTART);
323
+ if (!restartKey) {
324
+ addMessage(SignalMessageLevelEnum.ERROR, "No access key present");
325
+ return;
326
+ }
327
+ if (!instance) {
328
+ addMessage(SignalMessageLevelEnum.ERROR, "No instance has been established");
329
+ return;
330
+ }
331
+ let pods = cluster.data.filter((pod) => selectedNamespaces.includes(pod.namespace));
332
+ for (let pod of pods) {
333
+ let opsMessage = {
334
+ msgtype: "opsmessage",
335
+ action: InstanceMessageActionEnum.COMMAND,
336
+ flow: InstanceMessageFlowEnum.IMMEDIATE,
337
+ type: InstanceMessageTypeEnum.DATA,
338
+ channel: InstanceMessageChannelEnum.OPS,
339
+ instance: "",
340
+ id: "1",
341
+ accessKey: accessKeySerialize(restartKey),
342
+ command: OpsCommandEnum.RESTARTPOD,
343
+ namespace: pod.namespace,
344
+ group: "",
345
+ pod: pod.name,
346
+ container: ""
347
+ };
348
+ let routeMessage = {
349
+ msgtype: "routemessage",
350
+ accessKey: accessKeySerialize(restartKey),
351
+ destChannel: InstanceMessageChannelEnum.OPS,
352
+ action: InstanceMessageActionEnum.ROUTE,
353
+ flow: InstanceMessageFlowEnum.IMMEDIATE,
354
+ type: InstanceMessageTypeEnum.SIGNAL,
355
+ channel: InstanceMessageChannelEnum.LOG,
356
+ instance,
357
+ data: opsMessage
358
+ };
359
+ websocket?.send(JSON.stringify(routeMessage));
360
+ }
361
+ };
254
362
  const actionButtons = () => {
255
- let hasViewKey = false;
363
+ let hasViewKey = false, hasRestartKey = false;
256
364
  let cluster = resources.find((cluster2) => cluster2.name === selectedClusterName);
257
- if (cluster) hasViewKey = Boolean(cluster.accessKeys.get(InstanceConfigScopeEnum.VIEW));
258
- return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(IconButton, { title: "Download", onClick: handleDownload, disabled: messages.length <= 1 }, /* @__PURE__ */ React.createElement(DownloadIcon, null)), /* @__PURE__ */ React.createElement(IconButton, { onClick: () => clickStart(kwirthLogOptionsRef.current), title: "Play", disabled: started || !paused || selectedPodNames.length === 0 || !hasViewKey }, /* @__PURE__ */ React.createElement(PlayIcon, null)), /* @__PURE__ */ React.createElement(IconButton, { onClick: clickPause, title: "Pause", disabled: !(started && !paused.current && selectedPodNames.length > 0) }, /* @__PURE__ */ React.createElement(PauseIcon, null)), /* @__PURE__ */ React.createElement(IconButton, { onClick: clickStop, title: "Stop", disabled: stopped || selectedPodNames.length === 0 }, /* @__PURE__ */ React.createElement(StopIcon, null)));
365
+ if (cluster) {
366
+ hasViewKey = Boolean(cluster.accessKeys.get(InstanceConfigScopeEnum.VIEW));
367
+ hasRestartKey = Boolean(cluster.accessKeys.get(InstanceConfigScopeEnum.RESTART));
368
+ }
369
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, props.enableRestart && /* @__PURE__ */ React.createElement(IconButton, { title: "Restart", onClick: onClickRestart, disabled: selectedPodNames.length === 0 || !hasRestartKey || !websocket || !started }, /* @__PURE__ */ React.createElement(RefreshIcon, null)), /* @__PURE__ */ React.createElement(IconButton, { title: "Download", onClick: onClickDownload, disabled: messages.length <= 1 }, /* @__PURE__ */ React.createElement(DownloadIcon, null)), /* @__PURE__ */ React.createElement(IconButton, { onClick: () => clickStart(kwirthLogOptionsRef.current), title: "Play", disabled: started || !paused || selectedPodNames.length === 0 || !hasViewKey }, /* @__PURE__ */ React.createElement(PlayIcon, null)), /* @__PURE__ */ React.createElement(IconButton, { onClick: onClickPause, title: "Pause", disabled: !(started && !paused.current && selectedPodNames.length > 0) }, /* @__PURE__ */ React.createElement(PauseIcon, null)), /* @__PURE__ */ React.createElement(IconButton, { onClick: onClickStop, title: "Stop", disabled: stopped || selectedPodNames.length === 0 }, /* @__PURE__ */ React.createElement(StopIcon, null)));
259
370
  };
260
371
  const statusButtons = (title) => {
261
372
  const show = (level) => {
262
373
  setShowStatusDialog(true);
263
374
  setStatusLevel(level);
264
375
  };
265
- return /* @__PURE__ */ React.createElement(Grid, { container: true, direction: "row" }, /* @__PURE__ */ React.createElement(Grid, { item: true }, /* @__PURE__ */ React.createElement(Typography, { variant: "h5" }, 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) ? "gold" : "#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" } }))));
376
+ return /* @__PURE__ */ React.createElement(Grid, { container: true, direction: "row" }, /* @__PURE__ */ React.createElement(Grid, { item: true }, /* @__PURE__ */ React.createElement(Typography, { variant: "h5" }, 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" } }))));
266
377
  };
267
378
  const statusClear = (level) => {
268
379
  setStatusMessages(statusMessages.filter((m) => m.level !== level));
@@ -273,28 +384,28 @@ const EntityKwirthLogContent = () => {
273
384
  setSelectedPodNames(podNames);
274
385
  setSelectedContainerNames(containerNames);
275
386
  };
276
- const formatMessage = (m) => {
277
- if (!m.pod) {
278
- return /* @__PURE__ */ React.createElement(React.Fragment, null, m.text + "\n");
387
+ const formatMessage = (logLine) => {
388
+ if (!logLine.pod) {
389
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, logLine.text + "\n");
279
390
  }
280
391
  let podPrefix = /* @__PURE__ */ React.createElement(React.Fragment, null);
281
392
  if (selectedPodNames.length !== 1) {
282
- podPrefix = /* @__PURE__ */ React.createElement("span", { style: { color: "green" } }, m.pod + " ");
393
+ podPrefix = /* @__PURE__ */ React.createElement("span", { style: { color: "green" } }, logLine.pod + " ");
283
394
  }
284
395
  let containerPrefix = /* @__PURE__ */ React.createElement(React.Fragment, null);
285
396
  if (selectedContainerNames.length !== 1) {
286
- containerPrefix = /* @__PURE__ */ React.createElement("span", { style: { color: "blue" } }, m.container + " ");
397
+ containerPrefix = /* @__PURE__ */ React.createElement("span", { style: { color: "blue" } }, logLine.container + " ");
287
398
  }
288
- return /* @__PURE__ */ React.createElement(React.Fragment, null, podPrefix, containerPrefix, m.text + "\n");
399
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, podPrefix, containerPrefix, logLine.text + "\n");
289
400
  };
290
- return /* @__PURE__ */ React.createElement(React.Fragment, null, showError !== "" && /* @__PURE__ */ React.createElement(ShowError, { message: showError, onClose: () => setShowError("") }), 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_KWIRTH_LOCATION }), isKwirthAvailable(entity) && !loading && resources && resources.length === 0 && /* @__PURE__ */ React.createElement(ComponentNotFound, { error: ErrorType.NO_CLUSTERS, entity }), isKwirthAvailable(entity) && !loading && resources && resources.length > 0 && resources.reduce((sum, cluster) => sum + cluster.data.length, 0) === 0 && /* @__PURE__ */ React.createElement(ComponentNotFound, { error: ErrorType.NO_PODS, entity }), isKwirthAvailable(entity) && !loading && resources && resources.length > 0 && resources.reduce((sum, cluster) => sum + cluster.data.length, 0) > 0 && /* @__PURE__ */ React.createElement(Grid, { container: true, direction: "row", spacing: 3 }, /* @__PURE__ */ React.createElement(Grid, { container: true, item: true, xs: 2, direction: "column", spacing: 3 }, /* @__PURE__ */ React.createElement(Grid, { item: true }, /* @__PURE__ */ React.createElement(Card, null, /* @__PURE__ */ React.createElement(ClusterList, { resources, 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, xs: 10 }, !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: { maxHeight: "75vh" } }, /* @__PURE__ */ React.createElement(
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_KWIRTH_LOCATION }), isKwirthAvailable(entity) && !loading && resources && resources.length === 0 && /* @__PURE__ */ React.createElement(ComponentNotFound, { error: ErrorType.NO_CLUSTERS, entity }), isKwirthAvailable(entity) && !loading && resources && resources.length > 0 && resources.reduce((sum, cluster) => sum + cluster.data.length, 0) === 0 && /* @__PURE__ */ React.createElement(ComponentNotFound, { error: ErrorType.NO_PODS, entity }), isKwirthAvailable(entity) && !loading && resources && resources.length > 0 && resources.reduce((sum, cluster) => sum + cluster.data.length, 0) > 0 && /* @__PURE__ */ React.createElement(Box, { sx: { display: "flex", height: "70vh" } }, /* @__PURE__ */ React.createElement(Box, { sx: { width: "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, 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(Box, { sx: { flexGrow: 1, flex: 1, overflow: "hidden", p: 1, maxWidth: "85%" } }, !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(
291
402
  CardHeader,
292
403
  {
293
404
  title: statusButtons(selectedClusterName),
294
405
  style: { marginTop: -4, marginBottom: 4, flexShrink: 0 },
295
406
  action: actionButtons()
296
407
  }
297
- ), /* @__PURE__ */ React.createElement(Typography, { style: { marginLeft: 16, marginBottom: 4 } }, /* @__PURE__ */ React.createElement(ObjectSelector, { cluster: resources.find((cluster) => cluster.name === selectedClusterName), onSelect: onSelectObject, disabled: selectedClusterName === "" || started || paused.current, selectedNamespaces, selectedPodNames, selectedContainerNames })), /* @__PURE__ */ React.createElement(Divider, null), /* @__PURE__ */ React.createElement(CardContent, { style: { overflow: "auto" } }, /* @__PURE__ */ React.createElement("pre", { ref: preRef }, messages.map((m) => formatMessage(m))), /* @__PURE__ */ React.createElement("span", { ref: lastRef })))))), showStatusDialog && /* @__PURE__ */ React.createElement(StatusLog, { level: statusLevel, onClose: () => setShowStatusDialog(false), statusMessages, onClear: statusClear }));
408
+ ), /* @__PURE__ */ React.createElement(Typography, { style: { marginLeft: 16, marginBottom: 4 } }, /* @__PURE__ */ React.createElement(ObjectSelector, { cluster: resources.find((cluster) => cluster.name === selectedClusterName), onSelect: onSelectObject, disabled: selectedClusterName === "" || started || paused.current, selectedNamespaces, selectedPodNames, selectedContainerNames })), /* @__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", overflowX: "auto", width: "100%", flexGrow: 1 } }, /* @__PURE__ */ React.createElement("pre", { ref: preRef }, messages.map((m) => formatMessage(m))), /* @__PURE__ */ React.createElement("span", { ref: lastRef }))))))), showStatusDialog && /* @__PURE__ */ React.createElement(StatusLog, { level: statusLevel, onClose: () => setShowStatusDialog(false), statusMessages, onClear: statusClear }));
298
409
  };
299
410
 
300
411
  export { EntityKwirthLogContent };
@@ -1 +1 @@
1
- {"version":3,"file":"EntityKwirthLogContent.esm.js","sources":["../../../src/components/EntityKwirthLogContent/EntityKwirthLogContent.tsx"],"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 React, { useRef, useState } from 'react'\r\nimport useAsync from 'react-use/esm/useAsync'\r\n\r\nimport { Progress, WarningPanel } from '@backstage/core-components'\r\nimport { useApi } from '@backstage/core-plugin-api'\r\nimport { ANNOTATION_KWIRTH_LOCATION, isKwirthAvailable, ClusterValidPods } from '@jfvilas/plugin-kwirth-common'\r\nimport { MissingAnnotationEmptyState, useEntity } from '@backstage/plugin-catalog-react'\r\n\r\n// kwirthlog\r\nimport { kwirthLogApiRef } from '../../api'\r\nimport { accessKeySerialize, LogMessage, InstanceConfigActionEnum, InstanceConfigChannelEnum, InstanceConfigFlowEnum, InstanceConfigScopeEnum, InstanceConfigViewEnum, InstanceMessage, InstanceMessageTypeEnum, SignalMessage, SignalMessageLevelEnum, InstanceConfigObjectEnum, InstanceConfig } from '@jfvilas/kwirth-common'\r\n\r\n// kwirthlog components\r\nimport { ComponentNotFound, ErrorType } from '../ComponentNotFound'\r\nimport { Options } from '../Options'\r\nimport { ClusterList } from '../ClusterList'\r\nimport { ShowError } from '../ShowError'\r\nimport { StatusLog } from '../StatusLog'\r\n\r\n\r\n// Material-UI\r\nimport { Grid } from '@material-ui/core'\r\nimport { Card, CardHeader, CardContent } from '@material-ui/core'\r\nimport Divider from '@material-ui/core/Divider'\r\nimport IconButton from '@material-ui/core/IconButton'\r\nimport Typography from '@material-ui/core/Typography'\r\n\r\n// Icons\r\nimport PlayIcon from '@material-ui/icons/PlayArrow'\r\nimport PauseIcon from '@material-ui/icons/Pause'\r\nimport StopIcon from '@material-ui/icons/Stop'\r\nimport InfoIcon from '@material-ui/icons/Info'\r\nimport WarningIcon from '@material-ui/icons/Warning'\r\nimport ErrorIcon from '@material-ui/icons/Error'\r\nimport DownloadIcon from '@material-ui/icons/CloudDownload'\r\nimport KwirthLogLogo from '../../assets/kwirthlog-logo.svg'\r\nimport { ObjectSelector } from '../ObjectSelector'\r\n\r\nconst LOG_MAX_MESSAGES=1000;\r\n\r\nexport const EntityKwirthLogContent = () => { \r\n const { entity } = useEntity()\r\n const kwirthLogApi = useApi(kwirthLogApiRef)\r\n const [resources, setResources] = useState<ClusterValidPods[]>([])\r\n const [selectedClusterName, setSelectedClusterName] = useState('')\r\n const [_namespaceList, setNamespaceList] = useState<string[]>([]) //+++\r\n const [selectedNamespaces, setSelectedNamespaces] = useState<string[]>([])\r\n const [selectedPodNames, setSelectedPodNames] = useState<string[]>([])\r\n const [selectedContainerNames, setSelectedContainerNames] = useState<string[]>([])\r\n const [showError, setShowError] = useState('') //+++ review if this is needed once we have errorMessages\r\n const [started, setStarted] = useState(false)\r\n const [stopped, setStopped] = useState(true)\r\n const paused=useRef<boolean>(false)\r\n const [messages, setMessages] = useState<LogMessage[]>([])\r\n const [pendingMessages, setPendingMessages] = useState<LogMessage[]>([])\r\n const [statusMessages, setStatusMessages] = useState<SignalMessage[]>([])\r\n const [websocket, setWebsocket] = useState<WebSocket>()\r\n const kwirthLogOptionsRef = useRef<any>({timestamp:false, follow:true, fromStart:false})\r\n const [showStatusDialog, setShowStatusDialog] = useState(false)\r\n const [statusLevel, setStatusLevel] = useState<SignalMessageLevelEnum>(SignalMessageLevelEnum.INFO)\r\n const preRef = useRef<HTMLPreElement|null>(null)\r\n const lastRef = useRef<HTMLPreElement|null>(null)\r\n const [ backendVersion, setBackendVersion ] = useState<string>('')\r\n const { loading, error } = useAsync ( async () => {\r\n if (backendVersion==='') setBackendVersion(await kwirthLogApi.getVersion())\r\n var data = await kwirthLogApi.requestAccess(entity,'log', [InstanceConfigScopeEnum.VIEW,InstanceConfigScopeEnum.RESTART])\r\n setResources(data)\r\n })\r\n\r\n const clickStart = (options:any) => {\r\n if (!paused.current) {\r\n setStarted(true)\r\n paused.current=false\r\n setStopped(false)\r\n startLogViewer(options)\r\n }\r\n else {\r\n setMessages( (prev) => [ ...prev, ...pendingMessages])\r\n setPendingMessages([])\r\n paused.current=false\r\n setStarted(true)\r\n }\r\n }\r\n\r\n const clickPause = () => {\r\n setStarted(false)\r\n paused.current=true\r\n }\r\n\r\n const clickStop = () => {\r\n setStarted(false)\r\n setStopped(true)\r\n paused.current=false\r\n stopLogViewer()\r\n }\r\n\r\n const onSelectCluster = (name:string|undefined) => {\r\n if (name) {\r\n setSelectedClusterName(name)\r\n resources.filter(cluster => cluster.name===name).map ( x => {\r\n var namespaces=Array.from(new Set(x.data.map ( (p:any) => p.namespace))) as string[]\r\n setNamespaceList(namespaces)\r\n })\r\n setMessages([{\r\n channel: InstanceConfigChannelEnum.LOG,\r\n type: InstanceMessageTypeEnum.SIGNAL,\r\n text: 'Select namespace in order to decide which pod logs to view.',\r\n instance: ''\r\n }])\r\n setSelectedNamespaces([])\r\n setSelectedPodNames([])\r\n setSelectedContainerNames([])\r\n setStatusMessages([])\r\n clickStop()\r\n }\r\n }\r\n\r\n const processLogMessage = (wsEvent:any) => {\r\n let msg = JSON.parse(wsEvent.data) as InstanceMessage\r\n switch (msg.type) {\r\n case 'data':\r\n var lmsg = msg as LogMessage\r\n if (paused.current) {\r\n setPendingMessages((prev) => [ ...prev, lmsg ])\r\n }\r\n else {\r\n setMessages((prev) => {\r\n while (prev.length>LOG_MAX_MESSAGES-1) {\r\n prev.splice(0,1)\r\n }\r\n if (kwirthLogOptionsRef.current.follow && lastRef.current) lastRef.current.scrollIntoView({ behavior: 'instant', block: 'start' })\r\n return [ ...prev, lmsg ]\r\n })\r\n } \r\n break\r\n case 'signal':\r\n let smsg = msg as SignalMessage\r\n setStatusMessages ((prev) => [...prev, smsg])\r\n break\r\n default:\r\n console.log('Invalid message type:')\r\n console.log(msg)\r\n setStatusMessages ((prev) => [...prev, {\r\n channel: InstanceConfigChannelEnum.LOG,\r\n type: InstanceMessageTypeEnum.SIGNAL,\r\n level: SignalMessageLevelEnum.ERROR,\r\n text: 'Invalid message type received: '+msg.type,\r\n instance: ''\r\n }])\r\n break\r\n }\r\n }\r\n \r\n const websocketOnMessage = (wsEvent:any) => {\r\n let instanceMessage:InstanceMessage\r\n try {\r\n instanceMessage = JSON.parse(wsEvent.data) as InstanceMessage\r\n }\r\n catch (err) {\r\n console.log(err)\r\n console.log(wsEvent.data)\r\n return\r\n }\r\n\r\n switch(instanceMessage.channel) {\r\n case 'log':\r\n processLogMessage(wsEvent)\r\n break\r\n default:\r\n console.log('Invalid channel in message: ', instanceMessage)\r\n break\r\n }\r\n\r\n }\r\n\r\n const websocketOnOpen = (ws:WebSocket, options:any) => {\r\n let cluster=resources.find(cluster => cluster.name === selectedClusterName)\r\n if (!cluster) {\r\n //+++ setShowError(msg.text);\r\n return\r\n }\r\n let pods = cluster.data.filter(p => selectedNamespaces.includes(p.namespace))\r\n if (!pods) {\r\n //+++ setShowError(msg.text);\r\n return\r\n }\r\n console.log(`WS connected`)\r\n let accessKey = cluster.accessKeys.get(InstanceConfigScopeEnum.VIEW)\r\n if (accessKey) {\r\n let containers:string[] = []\r\n if (selectedContainerNames.length>0) {\r\n for(var p of selectedPodNames) {\r\n for (var c of selectedContainerNames) {\r\n containers.push(p+'+'+c)\r\n }\r\n }\r\n }\r\n let iConfig:InstanceConfig = {\r\n channel: InstanceConfigChannelEnum.LOG,\r\n objects: InstanceConfigObjectEnum.PODS,\r\n action: InstanceConfigActionEnum.START,\r\n flow: InstanceConfigFlowEnum.REQUEST,\r\n instance: '',\r\n accessKey: accessKeySerialize(accessKey),\r\n scope: InstanceConfigScopeEnum.VIEW,\r\n view: (selectedContainerNames.length>0 ? InstanceConfigViewEnum.CONTAINER : InstanceConfigViewEnum.POD),\r\n namespace: selectedNamespaces.join(','),\r\n group: '',\r\n pod: selectedPodNames.map(p => p).join(','),\r\n container: containers.join(','),\r\n data: {\r\n timestamp: options.timestamp,\r\n previous: false,\r\n maxMessages: LOG_MAX_MESSAGES,\r\n fromStart: options.fromStart\r\n }\r\n }\r\n ws.send(JSON.stringify(iConfig))\r\n }\r\n else {\r\n // +++ error to user\r\n }\r\n }\r\n\r\n const startLogViewer = (options:any) => {\r\n let cluster=resources.find(cluster => cluster.name===selectedClusterName);\r\n if (!cluster) {\r\n //+++ show wargning\r\n return\r\n }\r\n\r\n setMessages([])\r\n try {\r\n let ws = new WebSocket(cluster.url)\r\n ws.onopen = () => websocketOnOpen(ws, options)\r\n ws.onmessage = (event) => websocketOnMessage(event)\r\n ws.onclose = (event) => websocketOnClose(event)\r\n setWebsocket(ws)\r\n }\r\n catch (err) {\r\n setMessages([ {\r\n channel: InstanceConfigChannelEnum.LOG,\r\n type: InstanceMessageTypeEnum.DATA,\r\n text: `Error opening log stream: ${err}`,\r\n instance: ''\r\n } ])\r\n }\r\n\r\n }\r\n\r\n const websocketOnClose = (_event:any) => {\r\n console.log(`WS disconnected`)\r\n setStarted(false)\r\n paused.current=false\r\n setStopped(true)\r\n }\r\n\r\n const stopLogViewer = () => {\r\n messages.push({\r\n channel: InstanceConfigChannelEnum.LOG,\r\n type: InstanceMessageTypeEnum.DATA,\r\n text: '============================================================================================================================',\r\n instance: ''\r\n })\r\n websocket?.close()\r\n }\r\n\r\n const onChangeLogConfig = (options:any) => {\r\n kwirthLogOptionsRef.current=options\r\n if (started) {\r\n clickStart(options)\r\n }\r\n }\r\n\r\n const handleDownload = () => {\r\n let content = preRef.current!.innerHTML.replaceAll('<pre>','').replaceAll('</pre>','\\n')\r\n content = content.replaceAll('<span style=\"color: green;\">','')\r\n content = content.replaceAll('<span style=\"color: blue;\">','')\r\n content = content.replaceAll('</span>','')\r\n let filename = selectedClusterName+'-'+selectedNamespaces+'-'+entity.metadata.name+'.txt'\r\n let mimeType:string = 'text/plain'\r\n \r\n const blob = new Blob([content], { type: mimeType })\r\n const url = URL.createObjectURL(blob)\r\n const link = document.createElement('a')\r\n link.href = url\r\n link.download = filename\r\n document.body.appendChild(link)\r\n link.click()\r\n document.body.removeChild(link)\r\n URL.revokeObjectURL(url)\r\n }\r\n \r\n const actionButtons = () => {\r\n let hasViewKey=false\r\n let cluster=resources.find(cluster => cluster.name===selectedClusterName)\r\n if (cluster) hasViewKey = Boolean(cluster.accessKeys.get(InstanceConfigScopeEnum.VIEW))\r\n\r\n return <>\r\n <IconButton title='Download' onClick={handleDownload} disabled={messages.length<=1}>\r\n <DownloadIcon />\r\n </IconButton>\r\n <IconButton onClick={() => clickStart(kwirthLogOptionsRef.current)} title=\"Play\" disabled={started || !paused || selectedPodNames.length === 0 || !hasViewKey}>\r\n <PlayIcon />\r\n </IconButton>\r\n <IconButton onClick={clickPause} title=\"Pause\" disabled={!((started && !paused.current) && selectedPodNames.length > 0)}>\r\n <PauseIcon />\r\n </IconButton>\r\n <IconButton onClick={clickStop} title=\"Stop\" disabled={stopped || selectedPodNames.length === 0}>\r\n <StopIcon />\r\n </IconButton>\r\n </>\r\n }\r\n\r\n const statusButtons = (title:string) => {\r\n const show = (level:SignalMessageLevelEnum) => {\r\n setShowStatusDialog(true)\r\n setStatusLevel(level)\r\n }\r\n\r\n return (\r\n <Grid container direction='row' >\r\n <Grid item>\r\n <Typography variant='h5'>{title}</Typography>\r\n </Grid>\r\n <Grid item style={{marginTop:'-8px'}}>\r\n <IconButton title=\"info\" disabled={!statusMessages.some(m=>m.type === InstanceMessageTypeEnum.SIGNAL && m.level=== SignalMessageLevelEnum.INFO)} onClick={() => show(SignalMessageLevelEnum.INFO)}>\r\n <InfoIcon style={{ color:statusMessages.some(m=>m.type === InstanceMessageTypeEnum.SIGNAL && m.level=== SignalMessageLevelEnum.INFO)?'blue':'#BDBDBD'}}/>\r\n </IconButton>\r\n <IconButton title=\"warning\" disabled={!statusMessages.some(m=>m.type === InstanceMessageTypeEnum.SIGNAL && m.level=== SignalMessageLevelEnum.WARNING)} onClick={() => show(SignalMessageLevelEnum.WARNING)} style={{marginLeft:'-16px'}}>\r\n <WarningIcon style={{ color:statusMessages.some(m=>m.type === InstanceMessageTypeEnum.SIGNAL && m.level=== SignalMessageLevelEnum.WARNING)?'gold':'#BDBDBD'}}/>\r\n </IconButton>\r\n <IconButton title=\"error\" disabled={!statusMessages.some(m=>m.type === InstanceMessageTypeEnum.SIGNAL && m.level=== SignalMessageLevelEnum.ERROR)} onClick={() => show(SignalMessageLevelEnum.ERROR)} style={{marginLeft:'-16px'}}>\r\n <ErrorIcon style={{ color:statusMessages.some(m=>m.type === InstanceMessageTypeEnum.SIGNAL && m.level=== SignalMessageLevelEnum.ERROR)?'red':'#BDBDBD'}}/>\r\n </IconButton>\r\n </Grid>\r\n </Grid>\r\n )\r\n }\r\n\r\n const statusClear = (level: SignalMessageLevelEnum) => {\r\n setStatusMessages(statusMessages.filter(m=> m.level!==level))\r\n setShowStatusDialog(false)\r\n }\r\n \r\n const onSelectObject = (namespaces:string[], podNames:string[], containerNames:string[]) => {\r\n setSelectedNamespaces(namespaces)\r\n setSelectedPodNames(podNames)\r\n setSelectedContainerNames(containerNames)\r\n }\r\n\r\n const formatMessage = (m:LogMessage) => {\r\n if (!m.pod) {\r\n return <>{m.text+'\\n'}</>\r\n }\r\n\r\n let podPrefix = <></>\r\n if (selectedPodNames.length !== 1) {\r\n podPrefix = <span style={{color:\"green\"}}>{m.pod+' '}</span>\r\n }\r\n\r\n let containerPrefix = <></>\r\n if (selectedContainerNames.length !== 1){\r\n containerPrefix = <span style={{color:\"blue\"}}>{m.container+' '}</span>\r\n }\r\n return <>{podPrefix}{containerPrefix}{m.text+'\\n'}</>\r\n }\r\n\r\n return (<>\r\n { showError!=='' && <ShowError message={showError} onClose={() => setShowError('')}/> }\r\n\r\n { loading && <Progress/> }\r\n\r\n {!isKwirthAvailable(entity) && !loading && error && (\r\n <WarningPanel title={'An error has ocurred while obtaining data from kuebernetes clusters.'} message={error?.message} />\r\n )}\r\n\r\n {!isKwirthAvailable(entity) && !loading && (\r\n <MissingAnnotationEmptyState readMoreUrl='https://github.com/jfvilas/plugin-kwirth-log' annotation={ANNOTATION_KWIRTH_LOCATION}/>\r\n )}\r\n\r\n { isKwirthAvailable(entity) && !loading && resources && resources.length===0 &&\r\n <ComponentNotFound error={ErrorType.NO_CLUSTERS} entity={entity}/>\r\n }\r\n\r\n { isKwirthAvailable(entity) && !loading && resources && resources.length>0 && resources.reduce((sum,cluster) => sum+cluster.data.length, 0)===0 &&\r\n <ComponentNotFound error={ErrorType.NO_PODS} entity={entity}/>\r\n }\r\n\r\n { isKwirthAvailable(entity) && !loading && resources && resources.length>0 && resources.reduce((sum,cluster) => sum+cluster.data.length, 0)>0 &&\r\n <Grid container direction='row' spacing={3}>\r\n <Grid container item xs={2} direction='column' spacing={3}>\r\n <Grid item>\r\n <Card>\r\n <ClusterList resources={resources} selectedClusterName={selectedClusterName} onSelect={onSelectCluster}/>\r\n </Card>\r\n </Grid>\r\n <Grid item>\r\n <Card>\r\n <Options options={kwirthLogOptionsRef.current} onChange={onChangeLogConfig} disabled={selectedContainerNames.length === 0 || started || paused.current}/>\r\n </Card>\r\n </Grid>\r\n </Grid>\r\n\r\n <Grid item xs={10}>\r\n\r\n { !selectedClusterName && \r\n <img src={KwirthLogLogo} alt='No cluster selected' style={{ left:'40%', marginTop:'10%', width:'20%', position:'relative' }} />\r\n }\r\n\r\n { selectedClusterName && <>\r\n <Card style={{ maxHeight:'75vh'}}>\r\n <CardHeader\r\n title={statusButtons(selectedClusterName)}\r\n style={{marginTop:-4, marginBottom:4, flexShrink:0}}\r\n action={actionButtons()}\r\n />\r\n \r\n <Typography style={{marginLeft:16, marginBottom:4}}>\r\n <ObjectSelector cluster={resources.find(cluster => cluster.name === selectedClusterName)!} onSelect={onSelectObject} disabled={selectedClusterName === '' || started || paused.current} selectedNamespaces={selectedNamespaces} selectedPodNames={selectedPodNames} selectedContainerNames={selectedContainerNames}/>\r\n </Typography>\r\n <Divider/>\r\n <CardContent style={{ overflow: 'auto' }}>\r\n <pre ref={preRef}>\r\n { messages.map (m => formatMessage(m)) }\r\n </pre>\r\n <span ref={lastRef}></span>\r\n </CardContent>\r\n </Card>\r\n </>}\r\n\r\n </Grid>\r\n </Grid>\r\n }\r\n\r\n { showStatusDialog && <StatusLog level={statusLevel} onClose={() => setShowStatusDialog(false)} statusMessages={statusMessages} onClear={statusClear}/>}\r\n </>)\r\n}\r\n"],"names":["cluster","p"],"mappings":"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"}
1
+ {"version":3,"file":"EntityKwirthLogContent.esm.js","sources":["../../../src/components/EntityKwirthLogContent/EntityKwirthLogContent.tsx"],"sourcesContent":["/*\r\nCopyright 2025 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 React, { useRef, useState } from 'react'\r\nimport useAsync from 'react-use/esm/useAsync'\r\n\r\nimport { Progress, WarningPanel } from '@backstage/core-components'\r\nimport { alertApiRef, useApi } from '@backstage/core-plugin-api'\r\nimport { ANNOTATION_KWIRTH_LOCATION, isKwirthAvailable, ClusterValidPods, PodData, ILogLine, IStatusLine } from '@jfvilas/plugin-kwirth-common'\r\nimport { MissingAnnotationEmptyState, useEntity } from '@backstage/plugin-catalog-react'\r\n\r\n// kwirthlog\r\nimport { kwirthLogApiRef } from '../../api'\r\nimport { accessKeySerialize, ILogMessage, InstanceMessageActionEnum, InstanceConfigScopeEnum, InstanceConfigViewEnum, InstanceMessage, InstanceMessageTypeEnum, SignalMessage, SignalMessageLevelEnum, InstanceConfigObjectEnum, InstanceConfig, InstanceMessageFlowEnum, InstanceMessageChannelEnum, IOpsMessage, OpsCommandEnum, IRouteMessage, IOpsMessageResponse } from '@jfvilas/kwirth-common'\r\n\r\n// kwirthlog components\r\nimport { ComponentNotFound, ErrorType } from '../ComponentNotFound'\r\nimport { ObjectSelector } from '../ObjectSelector'\r\nimport { Options } from '../Options'\r\nimport { ClusterList } from '../ClusterList'\r\nimport { StatusLog } from '../StatusLog'\r\n\r\n\r\n// Material-UI\r\nimport { Grid, Card, CardHeader, CardContent, Box, Button } from '@material-ui/core'\r\nimport Divider from '@material-ui/core/Divider'\r\nimport IconButton from '@material-ui/core/IconButton'\r\nimport Typography from '@material-ui/core/Typography'\r\n\r\n// Icons\r\nimport PlayIcon from '@material-ui/icons/PlayArrow'\r\nimport PauseIcon from '@material-ui/icons/Pause'\r\nimport StopIcon from '@material-ui/icons/Stop'\r\nimport InfoIcon from '@material-ui/icons/Info'\r\nimport WarningIcon from '@material-ui/icons/Warning'\r\nimport ErrorIcon from '@material-ui/icons/Error'\r\nimport DownloadIcon from '@material-ui/icons/CloudDownload'\r\nimport KwirthLogLogo from '../../assets/kwirthlog-logo.svg'\r\nimport RefreshIcon from '@material-ui/icons/Refresh'\r\n\r\nconst LOG_MAX_MESSAGES=1000\r\n\r\nexport const EntityKwirthLogContent = (props:{ enableRestart: boolean }) => { \r\n const { entity } = useEntity()\r\n const kwirthLogApi = useApi(kwirthLogApiRef)\r\n const alertApi = useApi(alertApiRef)\r\n const [resources, setResources] = useState<ClusterValidPods[]>([])\r\n const [selectedClusterName, setSelectedClusterName] = useState('')\r\n const [selectedNamespaces, setSelectedNamespaces] = useState<string[]>([])\r\n const [selectedPodNames, setSelectedPodNames] = useState<string[]>([])\r\n const [selectedContainerNames, setSelectedContainerNames] = useState<string[]>([])\r\n const [started, setStarted] = useState(false)\r\n const [stopped, setStopped] = useState(true)\r\n const paused=useRef<boolean>(false)\r\n const [messages, setMessages] = useState<ILogLine[]>([])\r\n const [pendingMessages, setPendingMessages] = useState<ILogLine[]>([])\r\n const [statusMessages, setStatusMessages] = useState<IStatusLine[]>([])\r\n const [websocket, setWebsocket] = useState<WebSocket>()\r\n const [instance, setInstance] = useState<string>()\r\n const kwirthLogOptionsRef = useRef<any>({timestamp:false, follow:true, fromStart:false})\r\n const [showStatusDialog, setShowStatusDialog] = useState(false)\r\n const [statusLevel, setStatusLevel] = useState<SignalMessageLevelEnum>(SignalMessageLevelEnum.INFO)\r\n const preRef = useRef<HTMLPreElement|null>(null)\r\n const lastRef = useRef<HTMLPreElement|null>(null)\r\n const [ backendVersion, setBackendVersion ] = useState<string>('')\r\n const { loading, error } = useAsync ( async () => {\r\n if (backendVersion==='') setBackendVersion(await kwirthLogApi.getVersion())\r\n let reqScopes = [InstanceConfigScopeEnum.VIEW]\r\n if (props.enableRestart) reqScopes.push(InstanceConfigScopeEnum.RESTART)\r\n let data:ClusterValidPods[] = await kwirthLogApi.requestAccess(entity, InstanceMessageChannelEnum.LOG, reqScopes)\r\n setResources(data)\r\n })\r\n const buffer = useRef<Map<string,string>>(new Map())\r\n\r\n\r\n const clickStart = (options:any) => {\r\n if (!paused.current) {\r\n setStarted(true)\r\n paused.current=false\r\n setStopped(false)\r\n startLogViewer(options)\r\n }\r\n else {\r\n setMessages( (prev) => [ ...prev, ...pendingMessages])\r\n setPendingMessages([])\r\n paused.current=false\r\n setStarted(true)\r\n }\r\n }\r\n\r\n const onClickPause = () => {\r\n setStarted(false)\r\n paused.current=true\r\n }\r\n\r\n const onClickStop = () => {\r\n setStarted(false)\r\n setStopped(true)\r\n paused.current=false\r\n stopLogViewer()\r\n }\r\n\r\n const onSelectCluster = (name:string|undefined) => {\r\n if (name) {\r\n setSelectedClusterName(name)\r\n setMessages([{\r\n type: InstanceMessageTypeEnum.SIGNAL,\r\n text: 'Select namespace in order to decide which pod logs to view.',\r\n namespace: '',\r\n pod: '',\r\n container: ''\r\n }])\r\n setSelectedNamespaces([])\r\n setSelectedPodNames([])\r\n setSelectedContainerNames([])\r\n setStatusMessages([])\r\n onClickStop()\r\n }\r\n }\r\n\r\n const processLogMessage = (wsEvent:any) => {\r\n let instanceMessage = JSON.parse(wsEvent.data) as InstanceMessage\r\n switch (instanceMessage.type) {\r\n case InstanceMessageTypeEnum.DATA:\r\n let logMessage = instanceMessage as ILogMessage\r\n let bname = logMessage.namespace+'/'+logMessage.pod+'/'+logMessage.container\r\n let text = logMessage.text\r\n if (!buffer.current.has(bname)) buffer.current.set(bname,'')\r\n if (buffer.current.get(bname)) {\r\n text = buffer.current.get(bname) + text\r\n buffer.current.set(bname,'')\r\n }\r\n if (!text.endsWith('\\n')) {\r\n let i = text.lastIndexOf('\\n')\r\n buffer.current.set(bname,text.substring(i))\r\n text = text.substring(0,i)\r\n }\r\n\r\n for (let line of text.split('\\n')) {\r\n if (line.trim() === '') continue\r\n\r\n let logLine:ILogLine = {\r\n text: line,\r\n namespace: logMessage.namespace,\r\n pod: logMessage.pod,\r\n container: logMessage.container,\r\n type: logMessage.type\r\n }\r\n\r\n if (paused.current) {\r\n setPendingMessages((prev) => [ ...prev, logLine ])\r\n }\r\n else {\r\n setMessages((prev) => {\r\n while (prev.length>LOG_MAX_MESSAGES-1) {\r\n prev.splice(0,1)\r\n }\r\n if (kwirthLogOptionsRef.current.follow && lastRef.current) lastRef.current.scrollIntoView({ behavior: 'instant', block: 'start' })\r\n return [ ...prev, logLine ]\r\n })\r\n }\r\n }\r\n break\r\n case InstanceMessageTypeEnum.SIGNAL:\r\n if (instanceMessage.flow === InstanceMessageFlowEnum.RESPONSE && instanceMessage.action === InstanceMessageActionEnum.START) {\r\n if (instanceMessage.instance!=='')\r\n setInstance(instanceMessage.instance)\r\n else {\r\n let signalMessage = instanceMessage as SignalMessage\r\n alertApi.post({ message: signalMessage.text, severity:'error', display:'transient' })\r\n }\r\n }\r\n else {\r\n let signalMessage = instanceMessage as SignalMessage\r\n addMessage(signalMessage.level, signalMessage.text)\r\n switch(signalMessage.level) {\r\n case SignalMessageLevelEnum.INFO:\r\n alertApi.post({ message: signalMessage.text, severity:'info', display:'transient' })\r\n break\r\n case SignalMessageLevelEnum.WARNING:\r\n alertApi.post({ message: signalMessage.text, severity:'warning', display:'transient' })\r\n break\r\n case SignalMessageLevelEnum.ERROR:\r\n alertApi.post({ message: signalMessage.text, severity:'error', display:'transient' })\r\n break\r\n default:\r\n alertApi.post({ message: signalMessage.text, severity:'success', display:'transient' })\r\n break\r\n }\r\n }\r\n break\r\n default:\r\n addMessage(SignalMessageLevelEnum.ERROR, 'Invalid message type received: ' + instanceMessage.type)\r\n alertApi.post({ message: 'Invalid message type received: ' + instanceMessage.type, severity:'error', display:'transient' })\r\n break\r\n }\r\n }\r\n\r\n const addMessage = (level:SignalMessageLevelEnum, text:string) => {\r\n setStatusMessages ((prev) => [...prev, {\r\n level,\r\n text,\r\n type: InstanceMessageTypeEnum.SIGNAL,\r\n }])\r\n }\r\n\r\n const websocketOnMessage = (wsEvent:any) => {\r\n let instanceMessage:InstanceMessage\r\n try {\r\n instanceMessage = JSON.parse(wsEvent.data) as InstanceMessage\r\n }\r\n catch (err) {\r\n console.log(err)\r\n console.log(wsEvent.data)\r\n return\r\n }\r\n\r\n switch(instanceMessage.channel) {\r\n case InstanceMessageChannelEnum.LOG:\r\n processLogMessage(wsEvent)\r\n break\r\n case InstanceMessageChannelEnum.OPS:\r\n let opsMessage = instanceMessage as IOpsMessageResponse\r\n if (opsMessage.data?.data) \r\n addMessage (SignalMessageLevelEnum.WARNING, 'Operations message: '+opsMessage.data.data)\r\n else\r\n addMessage (SignalMessageLevelEnum.WARNING, 'Operations message: '+JSON.stringify(opsMessage))\r\n break\r\n default:\r\n addMessage (SignalMessageLevelEnum.ERROR, 'Invalid channel in message: '+instanceMessage.channel)\r\n addMessage (SignalMessageLevelEnum.ERROR, 'Invalid message: '+JSON.stringify(instanceMessage))\r\n break\r\n }\r\n }\r\n\r\n const websocketOnOpen = (ws:WebSocket, options:any) => {\r\n let cluster=resources.find(cluster => cluster.name === selectedClusterName)\r\n if (!cluster) {\r\n addMessage(SignalMessageLevelEnum.ERROR,'No cluster selected')\r\n return\r\n }\r\n let pods = cluster.data.filter(p => selectedNamespaces.includes(p.namespace))\r\n if (!pods) {\r\n addMessage(SignalMessageLevelEnum.ERROR,'No pods found')\r\n return\r\n }\r\n console.log(`WS connected`)\r\n let accessKey = cluster.accessKeys.get(InstanceConfigScopeEnum.VIEW)\r\n if (accessKey) {\r\n let containers:string[] = []\r\n if (selectedContainerNames.length>0) {\r\n for(var p of selectedPodNames) {\r\n for (var c of selectedContainerNames) {\r\n containers.push(p+'+'+c)\r\n }\r\n }\r\n }\r\n let iConfig:InstanceConfig = {\r\n channel: InstanceMessageChannelEnum.LOG,\r\n objects: InstanceConfigObjectEnum.PODS,\r\n action: InstanceMessageActionEnum.START,\r\n flow: InstanceMessageFlowEnum.REQUEST,\r\n instance: '',\r\n accessKey: accessKeySerialize(accessKey),\r\n scope: InstanceConfigScopeEnum.VIEW,\r\n view: (selectedContainerNames.length > 0 ? InstanceConfigViewEnum.CONTAINER : InstanceConfigViewEnum.POD),\r\n namespace: selectedNamespaces.join(','),\r\n group: '',\r\n pod: selectedPodNames.map(p => p).join(','),\r\n container: containers.join(','),\r\n data: {\r\n timestamp: options.timestamp,\r\n previous: false,\r\n maxMessages: LOG_MAX_MESSAGES,\r\n fromStart: options.fromStart\r\n },\r\n type: InstanceMessageTypeEnum.SIGNAL\r\n }\r\n ws.send(JSON.stringify(iConfig))\r\n }\r\n else {\r\n addMessage(SignalMessageLevelEnum.ERROR,'No accessKey for starting log streaming')\r\n return\r\n }\r\n }\r\n\r\n const startLogViewer = (options:any) => {\r\n let cluster=resources.find(cluster => cluster.name===selectedClusterName);\r\n if (!cluster) {\r\n addMessage(SignalMessageLevelEnum.ERROR,'No cluster selected')\r\n return\r\n }\r\n\r\n setMessages([])\r\n try {\r\n let ws = new WebSocket(cluster.url)\r\n ws.onopen = () => websocketOnOpen(ws, options)\r\n ws.onmessage = (event) => websocketOnMessage(event)\r\n ws.onclose = (event) => websocketOnClose(event)\r\n setWebsocket(ws)\r\n }\r\n catch (err) {\r\n setMessages([ {\r\n type: InstanceMessageTypeEnum.DATA,\r\n text: `Error opening log stream: ${err}`,\r\n namespace: '',\r\n pod: '',\r\n container: ''\r\n } ])\r\n }\r\n\r\n }\r\n\r\n const websocketOnClose = (_event:any) => {\r\n console.log(`WS disconnected`)\r\n setStarted(false)\r\n paused.current=false\r\n setStopped(true)\r\n }\r\n\r\n const stopLogViewer = () => {\r\n messages.push({\r\n type: InstanceMessageTypeEnum.DATA,\r\n text: '============================================================================================================================',\r\n namespace: '',\r\n pod: '',\r\n container: ''\r\n })\r\n websocket?.close()\r\n }\r\n\r\n const onChangeLogConfig = (options:any) => {\r\n kwirthLogOptionsRef.current=options\r\n if (started) {\r\n clickStart(options)\r\n }\r\n }\r\n\r\n const onClickDownload = () => {\r\n let content = preRef.current!.innerHTML.replaceAll('<pre>','').replaceAll('</pre>','\\n')\r\n content = content.replaceAll('<span style=\"color: green;\">','')\r\n content = content.replaceAll('<span style=\"color: blue;\">','')\r\n content = content.replaceAll('</span>','')\r\n let filename = selectedClusterName+'-'+selectedNamespaces+'-'+entity.metadata.name+'.txt'\r\n let mimeType:string = 'text/plain'\r\n \r\n const blob = new Blob([content], { type: mimeType })\r\n const url = URL.createObjectURL(blob)\r\n const link = document.createElement('a')\r\n link.href = url\r\n link.download = filename\r\n document.body.appendChild(link)\r\n link.click()\r\n document.body.removeChild(link)\r\n URL.revokeObjectURL(url)\r\n }\r\n\r\n const onClickRestart = () => {\r\n // we perform a route command from channel 'log' to channel 'ops'\r\n var cluster=resources.find(cluster => cluster.name===selectedClusterName);\r\n if (!cluster) {\r\n addMessage(SignalMessageLevelEnum.ERROR,'No cluster selected')\r\n return\r\n }\r\n let restartKey = cluster.accessKeys.get(InstanceConfigScopeEnum.RESTART)\r\n if (!restartKey) {\r\n addMessage(SignalMessageLevelEnum.ERROR,'No access key present')\r\n return\r\n }\r\n if (!instance) {\r\n addMessage(SignalMessageLevelEnum.ERROR,'No instance has been established')\r\n return\r\n }\r\n\r\n let pods:PodData[] = (cluster.data as PodData[]).filter(pod => selectedNamespaces.includes(pod.namespace))\r\n for (let pod of pods) {\r\n let opsMessage:IOpsMessage = {\r\n msgtype: 'opsmessage',\r\n action: InstanceMessageActionEnum.COMMAND,\r\n flow: InstanceMessageFlowEnum.IMMEDIATE,\r\n type: InstanceMessageTypeEnum.DATA,\r\n channel: InstanceMessageChannelEnum.OPS,\r\n instance: '',\r\n id: '1',\r\n accessKey: accessKeySerialize(restartKey),\r\n command: OpsCommandEnum.RESTARTPOD,\r\n namespace: pod.namespace,\r\n group: '',\r\n pod: pod.name,\r\n container: ''\r\n }\r\n let routeMessage: IRouteMessage = {\r\n msgtype: 'routemessage',\r\n accessKey: accessKeySerialize(restartKey),\r\n destChannel: InstanceMessageChannelEnum.OPS,\r\n action: InstanceMessageActionEnum.ROUTE,\r\n flow: InstanceMessageFlowEnum.IMMEDIATE,\r\n type: InstanceMessageTypeEnum.SIGNAL,\r\n channel: InstanceMessageChannelEnum.LOG,\r\n instance: instance,\r\n data: opsMessage\r\n }\r\n websocket?.send(JSON.stringify(routeMessage))\r\n }\r\n }\r\n\r\n const actionButtons = () => {\r\n let hasViewKey=false, hasRestartKey = false\r\n let cluster=resources.find(cluster => cluster.name===selectedClusterName)\r\n if (cluster) {\r\n hasViewKey = Boolean(cluster.accessKeys.get(InstanceConfigScopeEnum.VIEW))\r\n hasRestartKey = Boolean(cluster.accessKeys.get(InstanceConfigScopeEnum.RESTART))\r\n }\r\n\r\n return <>\r\n { props.enableRestart &&\r\n <IconButton title='Restart' onClick={onClickRestart} disabled={selectedPodNames.length === 0 || !hasRestartKey || !websocket || !started}>\r\n <RefreshIcon />\r\n </IconButton>\r\n }\r\n <IconButton title='Download' onClick={onClickDownload} disabled={messages.length<=1}>\r\n <DownloadIcon />\r\n </IconButton>\r\n <IconButton onClick={() => clickStart(kwirthLogOptionsRef.current)} title=\"Play\" disabled={started || !paused || selectedPodNames.length === 0 || !hasViewKey}>\r\n <PlayIcon />\r\n </IconButton>\r\n <IconButton onClick={onClickPause} title=\"Pause\" disabled={!((started && !paused.current) && selectedPodNames.length > 0)}>\r\n <PauseIcon />\r\n </IconButton>\r\n <IconButton onClick={onClickStop} title=\"Stop\" disabled={stopped || selectedPodNames.length === 0}>\r\n <StopIcon />\r\n </IconButton>\r\n </>\r\n }\r\n\r\n const statusButtons = (title:string) => {\r\n const show = (level:SignalMessageLevelEnum) => {\r\n setShowStatusDialog(true)\r\n setStatusLevel(level)\r\n }\r\n\r\n return (\r\n <Grid container direction='row' >\r\n <Grid item>\r\n <Typography variant='h5'>{title}</Typography>\r\n </Grid>\r\n <Grid item style={{marginTop:'-8px'}}>\r\n <IconButton title=\"info\" disabled={!statusMessages.some(m=>m.type === InstanceMessageTypeEnum.SIGNAL && m.level=== SignalMessageLevelEnum.INFO)} onClick={() => show(SignalMessageLevelEnum.INFO)}>\r\n <InfoIcon style={{ color:statusMessages.some(m=>m.type === InstanceMessageTypeEnum.SIGNAL && m.level=== SignalMessageLevelEnum.INFO)?'blue':'#BDBDBD'}}/>\r\n </IconButton>\r\n <IconButton title=\"warning\" disabled={!statusMessages.some(m=>m.type === InstanceMessageTypeEnum.SIGNAL && m.level=== SignalMessageLevelEnum.WARNING)} onClick={() => show(SignalMessageLevelEnum.WARNING)} style={{marginLeft:'-16px'}}>\r\n <WarningIcon style={{ color:statusMessages.some(m=>m.type === InstanceMessageTypeEnum.SIGNAL && m.level=== SignalMessageLevelEnum.WARNING)?'orange':'#BDBDBD'}}/>\r\n </IconButton>\r\n <IconButton title=\"error\" disabled={!statusMessages.some(m=>m.type === InstanceMessageTypeEnum.SIGNAL && m.level=== SignalMessageLevelEnum.ERROR)} onClick={() => show(SignalMessageLevelEnum.ERROR)} style={{marginLeft:'-16px'}}>\r\n <ErrorIcon style={{ color:statusMessages.some(m=>m.type === InstanceMessageTypeEnum.SIGNAL && m.level=== SignalMessageLevelEnum.ERROR)?'red':'#BDBDBD'}}/>\r\n </IconButton>\r\n </Grid>\r\n </Grid>\r\n )\r\n }\r\n\r\n const statusClear = (level: SignalMessageLevelEnum) => {\r\n setStatusMessages(statusMessages.filter(m=> m.level!==level))\r\n setShowStatusDialog(false)\r\n }\r\n \r\n const onSelectObject = (namespaces:string[], podNames:string[], containerNames:string[]) => {\r\n setSelectedNamespaces(namespaces)\r\n setSelectedPodNames(podNames)\r\n setSelectedContainerNames(containerNames)\r\n }\r\n\r\n const formatMessage = (logLine:ILogLine) => {\r\n if (!logLine.pod) {\r\n return <>{logLine.text+'\\n'}</>\r\n }\r\n\r\n let podPrefix = <></>\r\n if (selectedPodNames.length !== 1) {\r\n podPrefix = <span style={{color:\"green\"}}>{logLine.pod+' '}</span>\r\n }\r\n\r\n let containerPrefix = <></>\r\n if (selectedContainerNames.length !== 1){\r\n containerPrefix = <span style={{color:\"blue\"}}>{logLine.container+' '}</span>\r\n }\r\n return <>{podPrefix}{containerPrefix}{logLine.text+'\\n'}</>\r\n }\r\n\r\n return (<>\r\n\r\n { loading && <Progress/> }\r\n\r\n {!isKwirthAvailable(entity) && !loading && error && (\r\n <WarningPanel title={'An error has ocurred while obtaining data from kuebernetes clusters.'} message={error?.message} />\r\n )}\r\n\r\n {!isKwirthAvailable(entity) && !loading && (\r\n <MissingAnnotationEmptyState readMoreUrl='https://github.com/jfvilas/plugin-kwirth-log' annotation={ANNOTATION_KWIRTH_LOCATION}/>\r\n )}\r\n\r\n { isKwirthAvailable(entity) && !loading && resources && resources.length===0 &&\r\n <ComponentNotFound error={ErrorType.NO_CLUSTERS} entity={entity}/>\r\n }\r\n\r\n { isKwirthAvailable(entity) && !loading && resources && resources.length>0 && resources.reduce((sum,cluster) => sum+cluster.data.length, 0)===0 &&\r\n <ComponentNotFound error={ErrorType.NO_PODS} entity={entity}/>\r\n }\r\n\r\n { isKwirthAvailable(entity) && !loading && resources && resources.length>0 && resources.reduce((sum,cluster) => sum+cluster.data.length, 0)>0 &&\r\n <Box sx={{ display: 'flex', height:'70vh'}}>\r\n <Box sx={{ width: '200px'}}>\r\n <Grid container direction='column'>\r\n <Grid item> \r\n <Card>\r\n <ClusterList resources={resources} selectedClusterName={selectedClusterName} onSelect={onSelectCluster}/>\r\n </Card>\r\n </Grid>\r\n <Grid item>\r\n <Card>\r\n <Options options={kwirthLogOptionsRef.current} onChange={onChangeLogConfig} disabled={selectedContainerNames.length === 0 || started || paused.current}/>\r\n </Card>\r\n </Grid>\r\n </Grid>\r\n </Box>\r\n\r\n <Box sx={{ flexGrow: 1, flex:1, overflow:'hidden', p:1, maxWidth:'85%' }}>\r\n\r\n { !selectedClusterName && \r\n <img src={KwirthLogLogo} alt='No cluster selected' style={{ left:'40%', marginTop:'10%', width:'20%', position:'relative' }} />\r\n }\r\n\r\n { selectedClusterName && <>\r\n <Card style={{ marginTop:-8, height:'100%', display:'flex', flexDirection:'column' }}>\r\n <CardHeader\r\n title={statusButtons(selectedClusterName)}\r\n style={{marginTop:-4, marginBottom:4, flexShrink:0}}\r\n action={actionButtons()}\r\n />\r\n \r\n <Typography style={{marginLeft:16, marginBottom:4}}>\r\n <ObjectSelector cluster={resources.find(cluster => cluster.name === selectedClusterName)!} onSelect={onSelectObject} disabled={selectedClusterName === '' || started || paused.current} selectedNamespaces={selectedNamespaces} selectedPodNames={selectedPodNames} selectedContainerNames={selectedContainerNames}/>\r\n </Typography>\r\n <Divider/>\r\n {/* <CardContent>\r\n <Box style={{ display:'flex', flexDirection:'column', overflowY:'auto', overflowX:'auto', width:'100%', flexGrow:1, height:'55vh'}}> */}\r\n <CardContent style={{ flexGrow: 1, overflow: 'hidden', display: 'flex', flexDirection: 'column' }}>\r\n <Box style={{ overflowY: 'auto', overflowX: 'auto', width: '100%', flexGrow: 1 }}>\r\n\r\n <pre ref={preRef}>\r\n { messages.map (m => formatMessage(m)) }\r\n </pre>\r\n <span ref={lastRef}/>\r\n </Box> \r\n {/* <Box style={{ overflowY: 'auto', overflowX:'auto', whiteSpace: 'nowrap', maxHeight:'60vh' }}>\r\n <pre ref={preRef}>\r\n { messages.map (m => formatMessage(m)) }\r\n </pre>\r\n <span ref={lastRef}></span>\r\n </Box> */}\r\n </CardContent>\r\n </Card>\r\n </>}\r\n </Box>\r\n </Box>\r\n }\r\n { showStatusDialog && <StatusLog level={statusLevel} onClose={() => setShowStatusDialog(false)} statusMessages={statusMessages} onClear={statusClear}/>}\r\n </>)\r\n}\r\n"],"names":["cluster","p"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAoDA,MAAM,gBAAiB,GAAA,GAAA;AAEV,MAAA,sBAAA,GAAyB,CAAC,KAAqC,KAAA;AACxE,EAAM,MAAA,EAAE,MAAO,EAAA,GAAI,SAAU,EAAA;AAC7B,EAAM,MAAA,YAAA,GAAe,OAAO,eAAe,CAAA;AAC3C,EAAM,MAAA,QAAA,GAAW,OAAO,WAAW,CAAA;AACnC,EAAA,MAAM,CAAC,SAAW,EAAA,YAAY,CAAI,GAAA,QAAA,CAA6B,EAAE,CAAA;AACjE,EAAA,MAAM,CAAC,mBAAA,EAAqB,sBAAsB,CAAA,GAAI,SAAS,EAAE,CAAA;AACjE,EAAA,MAAM,CAAC,kBAAoB,EAAA,qBAAqB,CAAI,GAAA,QAAA,CAAmB,EAAE,CAAA;AACzE,EAAA,MAAM,CAAC,gBAAkB,EAAA,mBAAmB,CAAI,GAAA,QAAA,CAAmB,EAAE,CAAA;AACrE,EAAA,MAAM,CAAC,sBAAwB,EAAA,yBAAyB,CAAI,GAAA,QAAA,CAAmB,EAAE,CAAA;AACjF,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,SAAS,KAAK,CAAA;AAC5C,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,SAAS,IAAI,CAAA;AAC3C,EAAM,MAAA,MAAA,GAAO,OAAgB,KAAK,CAAA;AAClC,EAAA,MAAM,CAAC,QAAU,EAAA,WAAW,CAAI,GAAA,QAAA,CAAqB,EAAE,CAAA;AACvD,EAAA,MAAM,CAAC,eAAiB,EAAA,kBAAkB,CAAI,GAAA,QAAA,CAAqB,EAAE,CAAA;AACrE,EAAA,MAAM,CAAC,cAAgB,EAAA,iBAAiB,CAAI,GAAA,QAAA,CAAwB,EAAE,CAAA;AACtE,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAI,QAAoB,EAAA;AACtD,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAI,QAAiB,EAAA;AACjD,EAAM,MAAA,mBAAA,GAAsB,OAAY,EAAC,SAAA,EAAU,OAAO,MAAO,EAAA,IAAA,EAAM,SAAU,EAAA,KAAA,EAAM,CAAA;AACvF,EAAA,MAAM,CAAC,gBAAA,EAAkB,mBAAmB,CAAA,GAAI,SAAS,KAAK,CAAA;AAC9D,EAAA,MAAM,CAAC,WAAa,EAAA,cAAc,CAAI,GAAA,QAAA,CAAiC,uBAAuB,IAAI,CAAA;AAClG,EAAM,MAAA,MAAA,GAAS,OAA4B,IAAI,CAAA;AAC/C,EAAM,MAAA,OAAA,GAAU,OAA4B,IAAI,CAAA;AAChD,EAAA,MAAM,CAAE,cAAA,EAAgB,iBAAkB,CAAA,GAAI,SAAiB,EAAE,CAAA;AACjE,EAAA,MAAM,EAAE,OAAA,EAAS,KAAM,EAAA,GAAI,SAAW,YAAY;AAC9C,IAAA,IAAI,mBAAiB,EAAI,EAAA,iBAAA,CAAkB,MAAM,YAAA,CAAa,YAAY,CAAA;AAC1E,IAAI,IAAA,SAAA,GAAY,CAAC,uBAAA,CAAwB,IAAI,CAAA;AAC7C,IAAA,IAAI,KAAM,CAAA,aAAA,EAAyB,SAAA,CAAA,IAAA,CAAK,wBAAwB,OAAO,CAAA;AACvE,IAAA,IAAI,OAA0B,MAAM,YAAA,CAAa,cAAc,MAAQ,EAAA,0BAAA,CAA2B,KAAK,SAAS,CAAA;AAChH,IAAA,YAAA,CAAa,IAAI,CAAA;AAAA,GACpB,CAAA;AACD,EAAA,MAAM,MAAS,GAAA,MAAA,iBAA+B,IAAA,GAAA,EAAK,CAAA;AAGnD,EAAM,MAAA,UAAA,GAAa,CAAC,OAAgB,KAAA;AAChC,IAAI,IAAA,CAAC,OAAO,OAAS,EAAA;AACjB,MAAA,UAAA,CAAW,IAAI,CAAA;AACf,MAAA,MAAA,CAAO,OAAQ,GAAA,KAAA;AACf,MAAA,UAAA,CAAW,KAAK,CAAA;AAChB,MAAA,cAAA,CAAe,OAAO,CAAA;AAAA,KAErB,MAAA;AACD,MAAA,WAAA,CAAa,CAAC,IAAS,KAAA,CAAE,GAAG,IAAM,EAAA,GAAG,eAAe,CAAC,CAAA;AACrD,MAAA,kBAAA,CAAmB,EAAE,CAAA;AACrB,MAAA,MAAA,CAAO,OAAQ,GAAA,KAAA;AACf,MAAA,UAAA,CAAW,IAAI,CAAA;AAAA;AACnB,GACJ;AAEA,EAAA,MAAM,eAAe,MAAM;AACvB,IAAA,UAAA,CAAW,KAAK,CAAA;AAChB,IAAA,MAAA,CAAO,OAAQ,GAAA,IAAA;AAAA,GACnB;AAEA,EAAA,MAAM,cAAc,MAAM;AACtB,IAAA,UAAA,CAAW,KAAK,CAAA;AAChB,IAAA,UAAA,CAAW,IAAI,CAAA;AACf,IAAA,MAAA,CAAO,OAAQ,GAAA,KAAA;AACf,IAAc,aAAA,EAAA;AAAA,GAClB;AAEA,EAAM,MAAA,eAAA,GAAkB,CAAC,IAA0B,KAAA;AAC/C,IAAA,IAAI,IAAM,EAAA;AACN,MAAA,sBAAA,CAAuB,IAAI,CAAA;AAC3B,MAAA,WAAA,CAAY,CAAC;AAAA,QACT,MAAM,uBAAwB,CAAA,MAAA;AAAA,QAC9B,IAAM,EAAA,6DAAA;AAAA,QACN,SAAW,EAAA,EAAA;AAAA,QACX,GAAK,EAAA,EAAA;AAAA,QACL,SAAW,EAAA;AAAA,OACd,CAAC,CAAA;AACF,MAAA,qBAAA,CAAsB,EAAE,CAAA;AACxB,MAAA,mBAAA,CAAoB,EAAE,CAAA;AACtB,MAAA,yBAAA,CAA0B,EAAE,CAAA;AAC5B,MAAA,iBAAA,CAAkB,EAAE,CAAA;AACpB,MAAY,WAAA,EAAA;AAAA;AAChB,GACJ;AAEA,EAAM,MAAA,iBAAA,GAAoB,CAAC,OAAgB,KAAA;AACvC,IAAA,IAAI,eAAkB,GAAA,IAAA,CAAK,KAAM,CAAA,OAAA,CAAQ,IAAI,CAAA;AAC7C,IAAA,QAAQ,gBAAgB,IAAM;AAAA,MAC1B,KAAK,uBAAwB,CAAA,IAAA;AACzB,QAAA,IAAI,UAAa,GAAA,eAAA;AACjB,QAAA,IAAI,QAAQ,UAAW,CAAA,SAAA,GAAU,MAAI,UAAW,CAAA,GAAA,GAAI,MAAI,UAAW,CAAA,SAAA;AACnE,QAAA,IAAI,OAAO,UAAW,CAAA,IAAA;AACtB,QAAI,IAAA,CAAC,MAAO,CAAA,OAAA,CAAQ,GAAI,CAAA,KAAK,GAAU,MAAA,CAAA,OAAA,CAAQ,GAAI,CAAA,KAAA,EAAM,EAAE,CAAA;AAC3D,QAAA,IAAI,MAAO,CAAA,OAAA,CAAQ,GAAI,CAAA,KAAK,CAAG,EAAA;AAC3B,UAAA,IAAA,GAAO,MAAO,CAAA,OAAA,CAAQ,GAAI,CAAA,KAAK,CAAI,GAAA,IAAA;AACnC,UAAO,MAAA,CAAA,OAAA,CAAQ,GAAI,CAAA,KAAA,EAAM,EAAE,CAAA;AAAA;AAE/B,QAAA,IAAI,CAAC,IAAA,CAAK,QAAS,CAAA,IAAI,CAAG,EAAA;AACtB,UAAI,IAAA,CAAA,GAAI,IAAK,CAAA,WAAA,CAAY,IAAI,CAAA;AAC7B,UAAA,MAAA,CAAO,QAAQ,GAAI,CAAA,KAAA,EAAM,IAAK,CAAA,SAAA,CAAU,CAAC,CAAC,CAAA;AAC1C,UAAO,IAAA,GAAA,IAAA,CAAK,SAAU,CAAA,CAAA,EAAE,CAAC,CAAA;AAAA;AAG7B,QAAA,KAAA,IAAS,IAAQ,IAAA,IAAA,CAAK,KAAM,CAAA,IAAI,CAAG,EAAA;AAC/B,UAAI,IAAA,IAAA,CAAK,IAAK,EAAA,KAAM,EAAI,EAAA;AAExB,UAAA,IAAI,OAAmB,GAAA;AAAA,YACnB,IAAM,EAAA,IAAA;AAAA,YACN,WAAW,UAAW,CAAA,SAAA;AAAA,YACtB,KAAK,UAAW,CAAA,GAAA;AAAA,YAChB,WAAW,UAAW,CAAA,SAAA;AAAA,YACtB,MAAM,UAAW,CAAA;AAAA,WACrB;AAEA,UAAA,IAAI,OAAO,OAAS,EAAA;AAChB,YAAA,kBAAA,CAAmB,CAAC,IAAS,KAAA,CAAE,GAAG,IAAA,EAAM,OAAQ,CAAC,CAAA;AAAA,WAEhD,MAAA;AACD,YAAA,WAAA,CAAY,CAAC,IAAS,KAAA;AAClB,cAAO,OAAA,IAAA,CAAK,MAAO,GAAA,gBAAA,GAAiB,CAAG,EAAA;AACnC,gBAAK,IAAA,CAAA,MAAA,CAAO,GAAE,CAAC,CAAA;AAAA;AAEnB,cAAA,IAAI,mBAAoB,CAAA,OAAA,CAAQ,MAAU,IAAA,OAAA,CAAQ,OAAS,EAAA,OAAA,CAAQ,OAAQ,CAAA,cAAA,CAAe,EAAE,QAAA,EAAU,SAAW,EAAA,KAAA,EAAO,SAAS,CAAA;AACjI,cAAO,OAAA,CAAE,GAAG,IAAA,EAAM,OAAQ,CAAA;AAAA,aAC7B,CAAA;AAAA;AACL;AAEJ,QAAA;AAAA,MACJ,KAAK,uBAAwB,CAAA,MAAA;AACzB,QAAA,IAAI,gBAAgB,IAAS,KAAA,uBAAA,CAAwB,YAAY,eAAgB,CAAA,MAAA,KAAW,0BAA0B,KAAO,EAAA;AACzH,UAAA,IAAI,gBAAgB,QAAW,KAAA,EAAA;AAC3B,YAAA,WAAA,CAAY,gBAAgB,QAAQ,CAAA;AAAA,eACnC;AACD,YAAA,IAAI,aAAgB,GAAA,eAAA;AACpB,YAAS,QAAA,CAAA,IAAA,CAAK,EAAE,OAAS,EAAA,aAAA,CAAc,MAAM,QAAS,EAAA,OAAA,EAAS,OAAQ,EAAA,WAAA,EAAa,CAAA;AAAA;AACxF,SAEC,MAAA;AACD,UAAA,IAAI,aAAgB,GAAA,eAAA;AACpB,UAAW,UAAA,CAAA,aAAA,CAAc,KAAO,EAAA,aAAA,CAAc,IAAI,CAAA;AAClD,UAAA,QAAO,cAAc,KAAO;AAAA,YACxB,KAAK,sBAAuB,CAAA,IAAA;AACxB,cAAS,QAAA,CAAA,IAAA,CAAK,EAAE,OAAS,EAAA,aAAA,CAAc,MAAM,QAAS,EAAA,MAAA,EAAQ,OAAQ,EAAA,WAAA,EAAa,CAAA;AACnF,cAAA;AAAA,YACJ,KAAK,sBAAuB,CAAA,OAAA;AACxB,cAAS,QAAA,CAAA,IAAA,CAAK,EAAE,OAAS,EAAA,aAAA,CAAc,MAAM,QAAS,EAAA,SAAA,EAAW,OAAQ,EAAA,WAAA,EAAa,CAAA;AACtF,cAAA;AAAA,YACJ,KAAK,sBAAuB,CAAA,KAAA;AACxB,cAAS,QAAA,CAAA,IAAA,CAAK,EAAE,OAAS,EAAA,aAAA,CAAc,MAAM,QAAS,EAAA,OAAA,EAAS,OAAQ,EAAA,WAAA,EAAa,CAAA;AACpF,cAAA;AAAA,YACJ;AACI,cAAS,QAAA,CAAA,IAAA,CAAK,EAAE,OAAS,EAAA,aAAA,CAAc,MAAM,QAAS,EAAA,SAAA,EAAW,OAAQ,EAAA,WAAA,EAAa,CAAA;AACtF,cAAA;AAAA;AACR;AAEJ,QAAA;AAAA,MACJ;AACI,QAAA,UAAA,CAAW,sBAAuB,CAAA,KAAA,EAAO,iCAAoC,GAAA,eAAA,CAAgB,IAAI,CAAA;AACjG,QAAS,QAAA,CAAA,IAAA,CAAK,EAAE,OAAA,EAAS,iCAAoC,GAAA,eAAA,CAAgB,MAAM,QAAS,EAAA,OAAA,EAAS,OAAQ,EAAA,WAAA,EAAa,CAAA;AAC1H,QAAA;AAAA;AACR,GACJ;AAEA,EAAM,MAAA,UAAA,GAAa,CAAC,KAAA,EAA8B,IAAgB,KAAA;AAC9D,IAAA,iBAAA,CAAmB,CAAC,IAAA,KAAS,CAAC,GAAG,IAAM,EAAA;AAAA,MACnC,KAAA;AAAA,MACA,IAAA;AAAA,MACA,MAAM,uBAAwB,CAAA;AAAA,KACjC,CAAC,CAAA;AAAA,GACN;AAEA,EAAM,MAAA,kBAAA,GAAqB,CAAC,OAAgB,KAAA;AACxC,IAAI,IAAA,eAAA;AACJ,IAAI,IAAA;AACA,MAAkB,eAAA,GAAA,IAAA,CAAK,KAAM,CAAA,OAAA,CAAQ,IAAI,CAAA;AAAA,aAEtC,GAAK,EAAA;AACR,MAAA,OAAA,CAAQ,IAAI,GAAG,CAAA;AACf,MAAQ,OAAA,CAAA,GAAA,CAAI,QAAQ,IAAI,CAAA;AACxB,MAAA;AAAA;AAGJ,IAAA,QAAO,gBAAgB,OAAS;AAAA,MAC5B,KAAK,0BAA2B,CAAA,GAAA;AAC5B,QAAA,iBAAA,CAAkB,OAAO,CAAA;AACzB,QAAA;AAAA,MACJ,KAAK,0BAA2B,CAAA,GAAA;AAC5B,QAAA,IAAI,UAAa,GAAA,eAAA;AACjB,QAAA,IAAI,WAAW,IAAM,EAAA,IAAA;AACjB,UAAA,UAAA,CAAY,sBAAuB,CAAA,OAAA,EAAS,sBAAuB,GAAA,UAAA,CAAW,KAAK,IAAI,CAAA;AAAA;AAEvF,UAAA,UAAA,CAAY,uBAAuB,OAAS,EAAA,sBAAA,GAAuB,IAAK,CAAA,SAAA,CAAU,UAAU,CAAC,CAAA;AACjG,QAAA;AAAA,MACJ;AACI,QAAA,UAAA,CAAY,sBAAuB,CAAA,KAAA,EAAO,8BAA+B,GAAA,eAAA,CAAgB,OAAO,CAAA;AAChG,QAAA,UAAA,CAAY,uBAAuB,KAAO,EAAA,mBAAA,GAAoB,IAAK,CAAA,SAAA,CAAU,eAAe,CAAC,CAAA;AAC7F,QAAA;AAAA;AACR,GACJ;AAEA,EAAM,MAAA,eAAA,GAAkB,CAAC,EAAA,EAAc,OAAgB,KAAA;AACnD,IAAA,IAAI,UAAQ,SAAU,CAAA,IAAA,CAAK,CAAAA,QAAWA,KAAAA,QAAAA,CAAQ,SAAS,mBAAmB,CAAA;AAC1E,IAAA,IAAI,CAAC,OAAS,EAAA;AACV,MAAW,UAAA,CAAA,sBAAA,CAAuB,OAAM,qBAAqB,CAAA;AAC7D,MAAA;AAAA;AAEJ,IAAI,IAAA,IAAA,GAAO,OAAQ,CAAA,IAAA,CAAK,MAAO,CAAA,CAAAC,OAAK,kBAAmB,CAAA,QAAA,CAASA,EAAE,CAAA,SAAS,CAAC,CAAA;AAC5E,IAAA,IAAI,CAAC,IAAM,EAAA;AACP,MAAW,UAAA,CAAA,sBAAA,CAAuB,OAAM,eAAe,CAAA;AACvD,MAAA;AAAA;AAEJ,IAAA,OAAA,CAAQ,IAAI,CAAc,YAAA,CAAA,CAAA;AAC1B,IAAA,IAAI,SAAY,GAAA,OAAA,CAAQ,UAAW,CAAA,GAAA,CAAI,wBAAwB,IAAI,CAAA;AACnE,IAAA,IAAI,SAAW,EAAA;AACX,MAAA,IAAI,aAAsB,EAAC;AAC3B,MAAI,IAAA,sBAAA,CAAuB,SAAO,CAAG,EAAA;AACjC,QAAA,KAAA,IAAQ,KAAK,gBAAkB,EAAA;AAC3B,UAAA,KAAA,IAAS,KAAK,sBAAwB,EAAA;AAClC,YAAW,UAAA,CAAA,IAAA,CAAK,CAAE,GAAA,GAAA,GAAI,CAAC,CAAA;AAAA;AAC3B;AACJ;AAEJ,MAAA,IAAI,OAAyB,GAAA;AAAA,QACzB,SAAS,0BAA2B,CAAA,GAAA;AAAA,QACpC,SAAS,wBAAyB,CAAA,IAAA;AAAA,QAClC,QAAQ,yBAA0B,CAAA,KAAA;AAAA,QAClC,MAAM,uBAAwB,CAAA,OAAA;AAAA,QAC9B,QAAU,EAAA,EAAA;AAAA,QACV,SAAA,EAAW,mBAAmB,SAAS,CAAA;AAAA,QACvC,OAAO,uBAAwB,CAAA,IAAA;AAAA,QAC/B,MAAO,sBAAuB,CAAA,MAAA,GAAS,CAAI,GAAA,sBAAA,CAAuB,YAAY,sBAAuB,CAAA,GAAA;AAAA,QACrG,SAAA,EAAW,kBAAmB,CAAA,IAAA,CAAK,GAAG,CAAA;AAAA,QACtC,KAAO,EAAA,EAAA;AAAA,QACP,GAAA,EAAK,iBAAiB,GAAI,CAAA,CAAAA,OAAKA,EAAC,CAAA,CAAE,KAAK,GAAG,CAAA;AAAA,QAC1C,SAAA,EAAW,UAAW,CAAA,IAAA,CAAK,GAAG,CAAA;AAAA,QAC9B,IAAM,EAAA;AAAA,UACF,WAAW,OAAQ,CAAA,SAAA;AAAA,UACnB,QAAU,EAAA,KAAA;AAAA,UACV,WAAa,EAAA,gBAAA;AAAA,UACb,WAAW,OAAQ,CAAA;AAAA,SACvB;AAAA,QACA,MAAM,uBAAwB,CAAA;AAAA,OAClC;AACA,MAAA,EAAA,CAAG,IAAK,CAAA,IAAA,CAAK,SAAU,CAAA,OAAO,CAAC,CAAA;AAAA,KAE9B,MAAA;AACD,MAAW,UAAA,CAAA,sBAAA,CAAuB,OAAM,yCAAyC,CAAA;AACjF,MAAA;AAAA;AACJ,GACJ;AAEA,EAAM,MAAA,cAAA,GAAiB,CAAC,OAAgB,KAAA;AACpC,IAAA,IAAI,UAAQ,SAAU,CAAA,IAAA,CAAK,CAAAD,QAAWA,KAAAA,QAAAA,CAAQ,SAAO,mBAAmB,CAAA;AACxE,IAAA,IAAI,CAAC,OAAS,EAAA;AACV,MAAW,UAAA,CAAA,sBAAA,CAAuB,OAAM,qBAAqB,CAAA;AAC7D,MAAA;AAAA;AAGJ,IAAA,WAAA,CAAY,EAAE,CAAA;AACd,IAAI,IAAA;AACA,MAAA,IAAI,EAAK,GAAA,IAAI,SAAU,CAAA,OAAA,CAAQ,GAAG,CAAA;AAClC,MAAA,EAAA,CAAG,MAAS,GAAA,MAAM,eAAgB,CAAA,EAAA,EAAI,OAAO,CAAA;AAC7C,MAAA,EAAA,CAAG,SAAY,GAAA,CAAC,KAAU,KAAA,kBAAA,CAAmB,KAAK,CAAA;AAClD,MAAA,EAAA,CAAG,OAAU,GAAA,CAAC,KAAU,KAAA,gBAAA,CAAiB,KAAK,CAAA;AAC9C,MAAA,YAAA,CAAa,EAAE,CAAA;AAAA,aAEZ,GAAK,EAAA;AACR,MAAA,WAAA,CAAY,CAAE;AAAA,QACV,MAAM,uBAAwB,CAAA,IAAA;AAAA,QAC9B,IAAA,EAAM,6BAA6B,GAAG,CAAA,CAAA;AAAA,QACtC,SAAW,EAAA,EAAA;AAAA,QACX,GAAK,EAAA,EAAA;AAAA,QACL,SAAW,EAAA;AAAA,OACb,CAAC,CAAA;AAAA;AACP,GAEJ;AAEA,EAAM,MAAA,gBAAA,GAAmB,CAAC,MAAe,KAAA;AACvC,IAAA,OAAA,CAAQ,IAAI,CAAiB,eAAA,CAAA,CAAA;AAC7B,IAAA,UAAA,CAAW,KAAK,CAAA;AAChB,IAAA,MAAA,CAAO,OAAQ,GAAA,KAAA;AACf,IAAA,UAAA,CAAW,IAAI,CAAA;AAAA,GACjB;AAEA,EAAA,MAAM,gBAAgB,MAAM;AACxB,IAAA,QAAA,CAAS,IAAK,CAAA;AAAA,MACV,MAAM,uBAAwB,CAAA,IAAA;AAAA,MAC9B,IAAM,EAAA,8HAAA;AAAA,MACN,SAAW,EAAA,EAAA;AAAA,MACX,GAAK,EAAA,EAAA;AAAA,MACL,SAAW,EAAA;AAAA,KACd,CAAA;AACD,IAAA,SAAA,EAAW,KAAM,EAAA;AAAA,GACrB;AAEA,EAAM,MAAA,iBAAA,GAAoB,CAAC,OAAgB,KAAA;AACvC,IAAA,mBAAA,CAAoB,OAAQ,GAAA,OAAA;AAC5B,IAAA,IAAI,OAAS,EAAA;AACT,MAAA,UAAA,CAAW,OAAO,CAAA;AAAA;AACtB,GACJ;AAEA,EAAA,MAAM,kBAAkB,MAAM;AAC5B,IAAI,IAAA,OAAA,GAAU,MAAO,CAAA,OAAA,CAAS,SAAU,CAAA,UAAA,CAAW,SAAQ,EAAE,CAAA,CAAE,UAAW,CAAA,QAAA,EAAS,IAAI,CAAA;AACvF,IAAU,OAAA,GAAA,OAAA,CAAQ,UAAW,CAAA,8BAAA,EAA+B,EAAE,CAAA;AAC9D,IAAU,OAAA,GAAA,OAAA,CAAQ,UAAW,CAAA,6BAAA,EAA8B,EAAE,CAAA;AAC7D,IAAU,OAAA,GAAA,OAAA,CAAQ,UAAW,CAAA,SAAA,EAAU,EAAE,CAAA;AACzC,IAAA,IAAI,WAAW,mBAAoB,GAAA,GAAA,GAAI,qBAAmB,GAAI,GAAA,MAAA,CAAO,SAAS,IAAK,GAAA,MAAA;AACnF,IAAA,IAAI,QAAkB,GAAA,YAAA;AAEtB,IAAM,MAAA,IAAA,GAAO,IAAI,IAAK,CAAA,CAAC,OAAO,CAAG,EAAA,EAAE,IAAM,EAAA,QAAA,EAAU,CAAA;AACnD,IAAM,MAAA,GAAA,GAAM,GAAI,CAAA,eAAA,CAAgB,IAAI,CAAA;AACpC,IAAM,MAAA,IAAA,GAAO,QAAS,CAAA,aAAA,CAAc,GAAG,CAAA;AACvC,IAAA,IAAA,CAAK,IAAO,GAAA,GAAA;AACZ,IAAA,IAAA,CAAK,QAAW,GAAA,QAAA;AAChB,IAAS,QAAA,CAAA,IAAA,CAAK,YAAY,IAAI,CAAA;AAC9B,IAAA,IAAA,CAAK,KAAM,EAAA;AACX,IAAS,QAAA,CAAA,IAAA,CAAK,YAAY,IAAI,CAAA;AAC9B,IAAA,GAAA,CAAI,gBAAgB,GAAG,CAAA;AAAA,GACzB;AAEA,EAAA,MAAM,iBAAiB,MAAM;AAEzB,IAAA,IAAI,UAAQ,SAAU,CAAA,IAAA,CAAK,CAAAA,QAAWA,KAAAA,QAAAA,CAAQ,SAAO,mBAAmB,CAAA;AACxE,IAAA,IAAI,CAAC,OAAS,EAAA;AACV,MAAW,UAAA,CAAA,sBAAA,CAAuB,OAAM,qBAAqB,CAAA;AAC7D,MAAA;AAAA;AAEJ,IAAA,IAAI,UAAa,GAAA,OAAA,CAAQ,UAAW,CAAA,GAAA,CAAI,wBAAwB,OAAO,CAAA;AACvE,IAAA,IAAI,CAAC,UAAY,EAAA;AACb,MAAW,UAAA,CAAA,sBAAA,CAAuB,OAAM,uBAAuB,CAAA;AAC/D,MAAA;AAAA;AAEJ,IAAA,IAAI,CAAC,QAAU,EAAA;AACX,MAAW,UAAA,CAAA,sBAAA,CAAuB,OAAM,kCAAkC,CAAA;AAC1E,MAAA;AAAA;AAGJ,IAAI,IAAA,IAAA,GAAkB,QAAQ,IAAmB,CAAA,MAAA,CAAO,SAAO,kBAAmB,CAAA,QAAA,CAAS,GAAI,CAAA,SAAS,CAAC,CAAA;AACzG,IAAA,KAAA,IAAS,OAAO,IAAM,EAAA;AAClB,MAAA,IAAI,UAAyB,GAAA;AAAA,QACzB,OAAS,EAAA,YAAA;AAAA,QACT,QAAQ,yBAA0B,CAAA,OAAA;AAAA,QAClC,MAAM,uBAAwB,CAAA,SAAA;AAAA,QAC9B,MAAM,uBAAwB,CAAA,IAAA;AAAA,QAC9B,SAAS,0BAA2B,CAAA,GAAA;AAAA,QACpC,QAAU,EAAA,EAAA;AAAA,QACV,EAAI,EAAA,GAAA;AAAA,QACJ,SAAA,EAAW,mBAAmB,UAAU,CAAA;AAAA,QACxC,SAAS,cAAe,CAAA,UAAA;AAAA,QACxB,WAAW,GAAI,CAAA,SAAA;AAAA,QACf,KAAO,EAAA,EAAA;AAAA,QACP,KAAK,GAAI,CAAA,IAAA;AAAA,QACT,SAAW,EAAA;AAAA,OACf;AACA,MAAA,IAAI,YAA8B,GAAA;AAAA,QAC9B,OAAS,EAAA,cAAA;AAAA,QACT,SAAA,EAAW,mBAAmB,UAAU,CAAA;AAAA,QACxC,aAAa,0BAA2B,CAAA,GAAA;AAAA,QACxC,QAAQ,yBAA0B,CAAA,KAAA;AAAA,QAClC,MAAM,uBAAwB,CAAA,SAAA;AAAA,QAC9B,MAAM,uBAAwB,CAAA,MAAA;AAAA,QAC9B,SAAS,0BAA2B,CAAA,GAAA;AAAA,QACpC,QAAA;AAAA,QACA,IAAM,EAAA;AAAA,OACV;AACA,MAAA,SAAA,EAAW,IAAK,CAAA,IAAA,CAAK,SAAU,CAAA,YAAY,CAAC,CAAA;AAAA;AAChD,GACJ;AAEA,EAAA,MAAM,gBAAgB,MAAM;AACxB,IAAI,IAAA,UAAA,GAAW,OAAO,aAAgB,GAAA,KAAA;AACtC,IAAA,IAAI,UAAQ,SAAU,CAAA,IAAA,CAAK,CAAAA,QAAWA,KAAAA,QAAAA,CAAQ,SAAO,mBAAmB,CAAA;AACxE,IAAA,IAAI,OAAS,EAAA;AACT,MAAA,UAAA,GAAa,QAAQ,OAAQ,CAAA,UAAA,CAAW,GAAI,CAAA,uBAAA,CAAwB,IAAI,CAAC,CAAA;AACzE,MAAA,aAAA,GAAgB,QAAQ,OAAQ,CAAA,UAAA,CAAW,GAAI,CAAA,uBAAA,CAAwB,OAAO,CAAC,CAAA;AAAA;AAGnF,IAAO,uBAAA,KAAA,CAAA,aAAA,CAAA,KAAA,CAAA,QAAA,EAAA,IAAA,EACD,MAAM,aACJ,oBAAA,KAAA,CAAA,aAAA,CAAC,cAAW,KAAM,EAAA,SAAA,EAAU,SAAS,cAAgB,EAAA,QAAA,EAAU,iBAAiB,MAAW,KAAA,CAAA,IAAK,CAAC,aAAiB,IAAA,CAAC,aAAa,CAAC,OAAA,EAAA,sCAC5H,WAAY,EAAA,IAAA,CACjB,mBAEH,KAAA,CAAA,aAAA,CAAA,UAAA,EAAA,EAAW,OAAM,UAAW,EAAA,OAAA,EAAS,iBAAiB,QAAU,EAAA,QAAA,CAAS,UAAQ,CAC9E,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,kBAAa,CAClB,CAAA,sCACC,UAAW,EAAA,EAAA,OAAA,EAAS,MAAM,UAAW,CAAA,mBAAA,CAAoB,OAAO,CAAG,EAAA,KAAA,EAAM,QAAO,QAAU,EAAA,OAAA,IAAW,CAAC,MAAU,IAAA,gBAAA,CAAiB,WAAW,CAAK,IAAA,CAAC,8BAC9I,KAAA,CAAA,aAAA,CAAA,QAAA,EAAA,IAAS,CACd,CACA,kBAAA,KAAA,CAAA,aAAA,CAAC,cAAW,OAAS,EAAA,YAAA,EAAc,OAAM,OAAQ,EAAA,QAAA,EAAU,EAAG,OAAW,IAAA,CAAC,OAAO,OAAY,IAAA,gBAAA,CAAiB,SAAS,CACnH,CAAA,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,eAAU,CACf,CAAA,sCACC,UAAW,EAAA,EAAA,OAAA,EAAS,aAAa,KAAM,EAAA,MAAA,EAAO,UAAU,OAAW,IAAA,gBAAA,CAAiB,WAAW,CAC5F,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,QAAS,EAAA,IAAA,CACd,CACJ,CAAA;AAAA,GACJ;AAEA,EAAM,MAAA,aAAA,GAAgB,CAAC,KAAiB,KAAA;AACpC,IAAM,MAAA,IAAA,GAAO,CAAC,KAAiC,KAAA;AAC3C,MAAA,mBAAA,CAAoB,IAAI,CAAA;AACxB,MAAA,cAAA,CAAe,KAAK,CAAA;AAAA,KACxB;AAEA,IAAA,2CACK,IAAK,EAAA,EAAA,SAAA,EAAS,MAAC,SAAU,EAAA,KAAA,EAAA,sCACrB,IAAK,EAAA,EAAA,IAAA,EAAI,IACN,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,cAAW,OAAQ,EAAA,IAAA,EAAA,EAAM,KAAM,CACpC,CAAA,sCACC,IAAK,EAAA,EAAA,IAAA,EAAI,IAAC,EAAA,KAAA,EAAO,EAAC,SAAU,EAAA,MAAA,sBACxB,KAAA,CAAA,aAAA,CAAA,UAAA,EAAA,EAAW,OAAM,MAAO,EAAA,QAAA,EAAU,CAAC,cAAA,CAAe,KAAK,CAAG,CAAA,KAAA,CAAA,CAAE,SAAS,uBAAwB,CAAA,MAAA,IAAU,EAAE,KAAS,KAAA,sBAAA,CAAuB,IAAI,CAAA,EAAG,SAAS,MAAM,IAAA,CAAK,uBAAuB,IAAI,CAAA,EAAA,sCAC3L,QAAS,EAAA,EAAA,KAAA,EAAO,EAAE,KAAA,EAAM,eAAe,IAAK,CAAA,CAAA,CAAA,KAAG,EAAE,IAAS,KAAA,uBAAA,CAAwB,UAAU,CAAE,CAAA,KAAA,KAAS,sBAAuB,CAAA,IAAI,IAAE,MAAO,GAAA,SAAA,IAAW,CAC3J,CAAA,sCACC,UAAW,EAAA,EAAA,KAAA,EAAM,WAAU,QAAU,EAAA,CAAC,eAAe,IAAK,CAAA,CAAA,CAAA,KAAG,EAAE,IAAS,KAAA,uBAAA,CAAwB,UAAU,CAAE,CAAA,KAAA,KAAS,sBAAuB,CAAA,OAAO,GAAG,OAAS,EAAA,MAAM,KAAK,sBAAuB,CAAA,OAAO,GAAG,KAAO,EAAA,EAAC,UAAW,EAAA,OAAA,sBAC1N,KAAA,CAAA,aAAA,CAAA,WAAA,EAAA,EAAY,OAAO,EAAE,KAAA,EAAM,eAAe,IAAK,CAAA,CAAA,CAAA,KAAG,CAAE,CAAA,IAAA,KAAS,wBAAwB,MAAU,IAAA,CAAA,CAAE,UAAS,sBAAuB,CAAA,OAAO,IAAE,QAAS,GAAA,SAAA,EAAW,EAAA,CACnK,mBACC,KAAA,CAAA,aAAA,CAAA,UAAA,EAAA,EAAW,OAAM,OAAQ,EAAA,QAAA,EAAU,CAAC,cAAe,CAAA,IAAA,CAAK,CAAG,CAAA,KAAA,CAAA,CAAE,SAAS,uBAAwB,CAAA,MAAA,IAAU,EAAE,KAAS,KAAA,sBAAA,CAAuB,KAAK,CAAG,EAAA,OAAA,EAAS,MAAM,IAAA,CAAK,uBAAuB,KAAK,CAAA,EAAG,OAAO,EAAC,UAAA,EAAW,SACrN,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,SAAU,EAAA,EAAA,KAAA,EAAO,EAAE,KAAM,EAAA,cAAA,CAAe,KAAK,CAAG,CAAA,KAAA,CAAA,CAAE,SAAS,uBAAwB,CAAA,MAAA,IAAU,EAAE,KAAS,KAAA,sBAAA,CAAuB,KAAK,CAAE,GAAA,KAAA,GAAM,WAAW,EAAA,CAC5J,CACJ,CACJ,CAAA;AAAA,GAER;AAEA,EAAM,MAAA,WAAA,GAAc,CAAC,KAAkC,KAAA;AACnD,IAAA,iBAAA,CAAkB,eAAe,MAAO,CAAA,CAAA,CAAA,KAAI,CAAE,CAAA,KAAA,KAAQ,KAAK,CAAC,CAAA;AAC5D,IAAA,mBAAA,CAAoB,KAAK,CAAA;AAAA,GAC7B;AAEA,EAAA,MAAM,cAAiB,GAAA,CAAC,UAAqB,EAAA,QAAA,EAAmB,cAA4B,KAAA;AACxF,IAAA,qBAAA,CAAsB,UAAU,CAAA;AAChC,IAAA,mBAAA,CAAoB,QAAQ,CAAA;AAC5B,IAAA,yBAAA,CAA0B,cAAc,CAAA;AAAA,GAC5C;AAEA,EAAM,MAAA,aAAA,GAAgB,CAAC,OAAqB,KAAA;AACxC,IAAI,IAAA,CAAC,QAAQ,GAAK,EAAA;AACd,MAAO,uBAAA,KAAA,CAAA,aAAA,CAAA,KAAA,CAAA,QAAA,EAAA,IAAA,EAAG,OAAQ,CAAA,IAAA,GAAK,IAAK,CAAA;AAAA;AAGhC,IAAA,IAAI,4BAAc,KAAA,CAAA,aAAA,CAAA,KAAA,CAAA,QAAA,EAAA,IAAA,CAAA;AAClB,IAAI,IAAA,gBAAA,CAAiB,WAAW,CAAG,EAAA;AAC/B,MAAa,SAAA,mBAAA,KAAA,CAAA,aAAA,CAAC,UAAK,KAAO,EAAA,EAAC,OAAM,OAAO,EAAA,EAAA,EAAI,OAAQ,CAAA,GAAA,GAAI,GAAI,CAAA;AAAA;AAGhE,IAAA,IAAI,kCAAoB,KAAA,CAAA,aAAA,CAAA,KAAA,CAAA,QAAA,EAAA,IAAA,CAAA;AACxB,IAAI,IAAA,sBAAA,CAAuB,WAAW,CAAE,EAAA;AACpC,MAAkB,eAAA,mBAAA,KAAA,CAAA,aAAA,CAAC,UAAK,KAAO,EAAA,EAAC,OAAM,MAAM,EAAA,EAAA,EAAI,OAAQ,CAAA,SAAA,GAAU,GAAI,CAAA;AAAA;AAE1E,IAAA,uBAAU,KAAA,CAAA,aAAA,CAAA,KAAA,CAAA,QAAA,EAAA,IAAA,EAAA,SAAA,EAAW,eAAiB,EAAA,OAAA,CAAQ,OAAK,IAAK,CAAA;AAAA,GAC5D;AAEA,EAAQ,uBAAA,KAAA,CAAA,aAAA,CAAA,KAAA,CAAA,QAAA,EAAA,IAAA,EAEF,2BAAY,KAAA,CAAA,aAAA,CAAA,QAAA,EAAA,IAAQ,GAErB,CAAC,iBAAA,CAAkB,MAAM,CAAA,IAAK,CAAC,OAAA,IAAW,yBACtC,KAAA,CAAA,aAAA,CAAA,YAAA,EAAA,EAAa,OAAO,sEAAwE,EAAA,OAAA,EAAS,OAAO,OAAS,EAAA,CAAA,EAGzH,CAAC,iBAAA,CAAkB,MAAM,CAAA,IAAK,CAAC,OAC5B,oBAAA,KAAA,CAAA,aAAA,CAAC,+BAA4B,WAAY,EAAA,8CAAA,EAA+C,YAAY,0BAA2B,EAAA,CAAA,EAGjI,iBAAkB,CAAA,MAAM,CAAK,IAAA,CAAC,WAAW,SAAa,IAAA,SAAA,CAAU,MAAS,KAAA,CAAA,oBACtE,KAAA,CAAA,aAAA,CAAA,iBAAA,EAAA,EAAkB,OAAO,SAAU,CAAA,WAAA,EAAa,MAAe,EAAA,CAAA,EAGlE,iBAAkB,CAAA,MAAM,KAAK,CAAC,OAAA,IAAW,aAAa,SAAU,CAAA,MAAA,GAAO,KAAK,SAAU,CAAA,MAAA,CAAO,CAAC,GAAA,EAAI,OAAY,KAAA,GAAA,GAAI,QAAQ,IAAK,CAAA,MAAA,EAAQ,CAAC,CAAI,KAAA,CAAA,wCACzI,iBAAkB,EAAA,EAAA,KAAA,EAAO,SAAU,CAAA,OAAA,EAAS,MAAe,EAAA,CAAA,EAG9D,kBAAkB,MAAM,CAAA,IAAK,CAAC,OAAW,IAAA,SAAA,IAAa,UAAU,MAAO,GAAA,CAAA,IAAK,SAAU,CAAA,MAAA,CAAO,CAAC,GAAA,EAAI,YAAY,GAAI,GAAA,OAAA,CAAQ,IAAK,CAAA,MAAA,EAAQ,CAAC,CAAA,GAAE,qBACvI,KAAA,CAAA,aAAA,CAAA,GAAA,EAAA,EAAI,EAAI,EAAA,EAAE,OAAS,EAAA,MAAA,EAAQ,QAAO,MAAM,EAAA,EAAA,sCACpC,GAAI,EAAA,EAAA,EAAA,EAAI,EAAE,KAAO,EAAA,OAAA,EACd,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,IAAK,EAAA,EAAA,SAAA,EAAS,MAAC,SAAU,EAAA,QAAA,EAAA,sCACrB,IAAK,EAAA,EAAA,IAAA,EAAI,wBACL,KAAA,CAAA,aAAA,CAAA,IAAA,EAAA,IAAA,kBACI,KAAA,CAAA,aAAA,CAAA,WAAA,EAAA,EAAY,SAAsB,EAAA,mBAAA,EAA0C,UAAU,eAAgB,EAAA,CAC3G,CACJ,CACA,kBAAA,KAAA,CAAA,aAAA,CAAC,QAAK,IAAI,EAAA,IAAA,EAAA,kBACL,KAAA,CAAA,aAAA,CAAA,IAAA,EAAA,IAAA,kBACI,KAAA,CAAA,aAAA,CAAA,OAAA,EAAA,EAAQ,SAAS,mBAAoB,CAAA,OAAA,EAAS,QAAU,EAAA,iBAAA,EAAmB,QAAU,EAAA,sBAAA,CAAuB,WAAW,CAAK,IAAA,OAAA,IAAW,MAAO,CAAA,OAAA,EAAQ,CAC3J,CACJ,CACJ,CACJ,CAAA,sCAEC,GAAI,EAAA,EAAA,EAAA,EAAI,EAAE,QAAU,EAAA,CAAA,EAAG,IAAK,EAAA,CAAA,EAAG,QAAS,EAAA,QAAA,EAAU,GAAE,CAAG,EAAA,QAAA,EAAS,KAAM,EAAA,EAAA,EAEjE,CAAC,mBAAA,wCACE,KAAI,EAAA,EAAA,GAAA,EAAK,aAAe,EAAA,GAAA,EAAI,qBAAsB,EAAA,KAAA,EAAO,EAAE,IAAK,EAAA,KAAA,EAAO,WAAU,KAAO,EAAA,KAAA,EAAM,OAAO,QAAS,EAAA,UAAA,EAAc,EAAA,CAAA,EAG/H,mBAAuB,oBAAA,KAAA,CAAA,aAAA,CAAA,KAAA,CAAA,QAAA,EAAA,IAAA,sCACpB,IAAK,EAAA,EAAA,KAAA,EAAO,EAAE,SAAA,EAAU,EAAI,EAAA,MAAA,EAAO,QAAQ,OAAQ,EAAA,MAAA,EAAQ,aAAc,EAAA,QAAA,EACtE,EAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MACG,KAAA,EAAO,cAAc,mBAAmB,CAAA;AAAA,MACxC,OAAO,EAAC,SAAA,EAAU,IAAI,YAAa,EAAA,CAAA,EAAG,YAAW,CAAC,EAAA;AAAA,MAClD,QAAQ,aAAc;AAAA;AAAA,GAC1B,sCAEC,UAAW,EAAA,EAAA,KAAA,EAAO,EAAC,UAAW,EAAA,EAAA,EAAI,cAAa,CAAC,EAAA,EAAA,sCAC5C,cAAe,EAAA,EAAA,OAAA,EAAS,UAAU,IAAK,CAAA,CAAA,OAAA,KAAW,QAAQ,IAAS,KAAA,mBAAmB,CAAI,EAAA,QAAA,EAAU,cAAgB,EAAA,QAAA,EAAU,wBAAwB,EAAM,IAAA,OAAA,IAAW,OAAO,OAAS,EAAA,kBAAA,EAAwC,kBAAoC,sBAA+C,EAAA,CACvT,CACA,kBAAA,KAAA,CAAA,aAAA,CAAC,OAAO,EAAA,IAAA,CAAA,sCAGP,WAAY,EAAA,EAAA,KAAA,EAAO,EAAE,QAAU,EAAA,CAAA,EAAG,UAAU,QAAU,EAAA,OAAA,EAAS,MAAQ,EAAA,aAAA,EAAe,QAAS,EAAA,EAAA,sCAC3F,GAAI,EAAA,EAAA,KAAA,EAAO,EAAE,SAAW,EAAA,MAAA,EAAQ,WAAW,MAAQ,EAAA,KAAA,EAAO,QAAQ,QAAU,EAAA,CAAA,sBAExE,KAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EAAI,KAAK,MACJ,EAAA,EAAA,QAAA,CAAS,IAAK,CAAK,CAAA,KAAA,aAAA,CAAc,CAAC,CAAC,CACzC,CAAA,sCACC,MAAK,EAAA,EAAA,GAAA,EAAK,SAAQ,CACvB,CAOJ,CACJ,CACJ,CACJ,CACJ,CAAA,EAEF,gBAAoB,oBAAA,KAAA,CAAA,aAAA,CAAC,aAAU,KAAO,EAAA,WAAA,EAAa,SAAS,MAAM,mBAAA,CAAoB,KAAK,CAAG,EAAA,cAAA,EAAgC,OAAS,EAAA,WAAA,EAAY,CACzJ,CAAA;AACJ;;;;"}
@@ -2,7 +2,7 @@ import React, { useState } from 'react';
2
2
  import FormControl from '@material-ui/core/FormControl';
3
3
  import Select from '@material-ui/core/Select';
4
4
  import MenuItem from '@material-ui/core/MenuItem';
5
- import { Grid, Chip, Input, Checkbox, ListItemText } from '@material-ui/core';
5
+ import { Grid, Chip, Checkbox, ListItemText } from '@material-ui/core';
6
6
  import { InstanceConfigScopeEnum, parseResources } from '@jfvilas/kwirth-common';
7
7
 
8
8
  const ObjectSelector = (props) => {
@@ -44,8 +44,8 @@ const ObjectSelector = (props) => {
44
44
  if (!props.cluster.accessKeys.has(InstanceConfigScopeEnum.VIEW)) return false;
45
45
  let accessKey = props.cluster.accessKeys.get(InstanceConfigScopeEnum.VIEW);
46
46
  if (accessKey) {
47
- let resources = parseResources(accessKey?.resource);
48
- return resources.find((r) => r.namespace === namespace);
47
+ let resources = parseResources(accessKey.resources);
48
+ return resources.find((resource) => resource.namespaces === namespace);
49
49
  } else return false;
50
50
  };
51
51
  const getPodList = () => {
@@ -73,9 +73,9 @@ const ObjectSelector = (props) => {
73
73
  else
74
74
  return /* @__PURE__ */ React.createElement(Chip, { component: "span", key: index, label: ns, size: "small", color: "secondary", variant: "outlined" });
75
75
  }
76
- })), /* @__PURE__ */ React.createElement(Grid, { container: true, item: true, xs: 12, spacing: 2 }, /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 6 }, /* @__PURE__ */ React.createElement(FormControl, { size: "small", fullWidth: true }, /* @__PURE__ */ React.createElement(Select, { value: props.selectedPodNames, input: /* @__PURE__ */ React.createElement(Input, null), multiple: true, onChange: onPodNameChange, renderValue: (selected) => selected.join(", "), disabled: props.disabled || props.selectedNamespaces.length === 0 || getPodList().length === 1 }, getPodList().map((pod) => {
76
+ })), /* @__PURE__ */ React.createElement(Grid, { container: true, item: true, xs: 12, spacing: 2 }, /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 6 }, /* @__PURE__ */ React.createElement(FormControl, { size: "small", fullWidth: true }, /* @__PURE__ */ React.createElement(Select, { value: props.selectedPodNames, MenuProps: { variant: "menu" }, multiple: true, onChange: onPodNameChange, renderValue: (selected) => selected.join(", "), disabled: props.disabled || props.selectedNamespaces.length === 0 || getPodList().length === 1 }, getPodList().map((pod) => {
77
77
  return /* @__PURE__ */ React.createElement(MenuItem, { key: pod.name, value: pod.name }, /* @__PURE__ */ React.createElement(Checkbox, { checked: props.selectedPodNames.includes(pod.name) }), /* @__PURE__ */ React.createElement(ListItemText, { primary: pod.name }));
78
- })))), /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 6 }, /* @__PURE__ */ React.createElement(FormControl, { size: "small", fullWidth: true }, /* @__PURE__ */ React.createElement(Select, { value: props.selectedContainerNames, multiple: true, onChange: onContainerNameChange, renderValue: (selected) => selected.join(", "), disabled: props.disabled || props.selectedPodNames.length === 0 || getContainerList().length === 1 }, getContainerList().map((container) => {
78
+ })))), /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 6 }, /* @__PURE__ */ React.createElement(FormControl, { size: "small", fullWidth: true }, /* @__PURE__ */ React.createElement(Select, { value: props.selectedContainerNames, MenuProps: { variant: "menu" }, multiple: true, onChange: onContainerNameChange, renderValue: (selected) => selected.join(", "), disabled: props.disabled || props.selectedPodNames.length === 0 || getContainerList().length === 1 }, getContainerList().map((container) => {
79
79
  return /* @__PURE__ */ React.createElement(MenuItem, { key: container, value: container }, /* @__PURE__ */ React.createElement(Checkbox, { checked: props.selectedContainerNames.includes(container) }), /* @__PURE__ */ React.createElement(ListItemText, { primary: container }));
80
80
  }))))));
81
81
  };
@@ -1 +1 @@
1
- {"version":3,"file":"ObjectSelector.esm.js","sources":["../../../src/components/ObjectSelector/ObjectSelector.tsx"],"sourcesContent":["import React, { useState } from 'react'\r\nimport { ClusterValidPods } from '@jfvilas/plugin-kwirth-common'\r\nimport FormControl from '@material-ui/core/FormControl'\r\nimport Select from '@material-ui/core/Select'\r\nimport MenuItem from '@material-ui/core/MenuItem'\r\nimport { Checkbox, Chip, Grid, Input, ListItemText } from '@material-ui/core'\r\nimport { InstanceConfigScopeEnum, parseResources } from '@jfvilas/kwirth-common'\r\n\r\ninterface IProps {\r\n onSelect: (namespaces:string[], podNames:string[], containerNames:string[]) => void,\r\n cluster: ClusterValidPods,\r\n selectedNamespaces: string[],\r\n selectedPodNames: string[],\r\n selectedContainerNames: string[],\r\n disabled: boolean\r\n}\r\n\r\nconst ObjectSelector = (props: IProps) => {\r\n const [render, setRender] = useState(false)\r\n let pods = props.cluster.data\r\n let namespaceList = Array.from(new Set(pods.map(p => p.namespace)))\r\n\r\n const onNamespaceChange = (namespace:string) => {\r\n let i = props.selectedNamespaces.indexOf(namespace)\r\n if (i>=0)\r\n props.selectedNamespaces.splice(i,1)\r\n else\r\n props.selectedNamespaces.push(namespace)\r\n\r\n props.selectedPodNames.splice(0,props.selectedPodNames.length)\r\n let pods = getPodList()\r\n if (pods.length===1) props.selectedPodNames.push( ...pods.map(p => p.name) )\r\n\r\n props.selectedContainerNames.splice(0,props.selectedContainerNames.length)\r\n let containers = getContainerList()\r\n if (containers.length===1) {\r\n props.selectedContainerNames.push(...containers)\r\n props.onSelect([...props.selectedNamespaces], [...props.selectedPodNames], [...props.selectedContainerNames])\r\n }\r\n\r\n setRender(!render)\r\n };\r\n\r\n const onPodNameChange = (event : any) => {\r\n props.selectedPodNames.splice(0,props.selectedPodNames.length)\r\n props.selectedPodNames.push( ...event.target.value )\r\n\r\n props.selectedContainerNames.splice(0,props.selectedContainerNames.length)\r\n let containers = getContainerList()\r\n if (containers.length===1) props.selectedContainerNames.push(...containers)\r\n\r\n props.onSelect([...props.selectedNamespaces], [...props.selectedPodNames], [...props.selectedContainerNames])\r\n\r\n setRender(!render)\r\n };\r\n\r\n const onContainerNameChange = (event : any) => {\r\n props.selectedContainerNames.splice(0,props.selectedContainerNames.length)\r\n props.selectedContainerNames.push( ...event.target.value )\r\n props.onSelect([...props.selectedNamespaces], [...props.selectedPodNames], [...props.selectedContainerNames])\r\n };\r\n\r\n const existAccessKey = (namespace:string) => {\r\n if (!props.cluster.accessKeys.has(InstanceConfigScopeEnum.VIEW)) return false\r\n let accessKey = props.cluster.accessKeys.get(InstanceConfigScopeEnum.VIEW)\r\n if (accessKey) {\r\n let resources = parseResources(accessKey?.resource)\r\n return (resources.find(r => r.namespace === namespace))\r\n }\r\n else return false\r\n\r\n }\r\n\r\n const getPodList = () => {\r\n return Array.from(pods.filter(m => props.selectedNamespaces.includes(m.namespace)))\r\n }\r\n\r\n const getContainerList = () => {\r\n if (props.selectedNamespaces.length===0 || props.selectedPodNames.length===0) return []\r\n let validpods = pods.filter(pod => props.selectedNamespaces.includes(pod.namespace))\r\n validpods = validpods.filter(p => props.selectedPodNames.includes(p.name))\r\n let validcontainers:string[] = []\r\n for (var p of validpods) {\r\n validcontainers.push ( ...p.containers )\r\n }\r\n return Array.from(new Set(validcontainers))\r\n }\r\n\r\n return (\r\n <Grid container direction='column' spacing={0} style={{marginBottom:6, width:'100%'}}>\r\n <Grid item>\r\n {\r\n namespaceList.map ((ns,index) => {\r\n if (props.disabled) {\r\n if (existAccessKey(ns))\r\n return <Chip component={'span'} key={index} label={ns as string} variant={props.selectedNamespaces.includes(ns)?'default':'outlined'} size='small' color='default' />\r\n else\r\n return <Chip component={'span'} key={index} label={ns as string} size='small' color='default' variant={'outlined'}/>\r\n }\r\n else {\r\n if (existAccessKey(ns))\r\n return <Chip component={'span'} key={index} label={ns as string} onClick={() => onNamespaceChange(ns)} variant={props.selectedNamespaces.includes(ns)?'default':'outlined'} size='small' color='primary' />\r\n else\r\n return <Chip component={'span'} key={index} label={ns as string} size='small' color='secondary' variant={'outlined'}/>\r\n }\r\n })\r\n }\r\n </Grid>\r\n <Grid container item xs={12} spacing={2}>\r\n <Grid item xs={6}>\r\n <FormControl size='small' fullWidth>\r\n <Select value={props.selectedPodNames} input={<Input />} multiple onChange={onPodNameChange} renderValue={(selected) => (selected as string[]).join(', ')} disabled={props.disabled || props.selectedNamespaces.length===0 || getPodList().length===1}>\r\n {\r\n getPodList().map(pod => {\r\n return (\r\n <MenuItem key={pod.name} value={pod.name}>\r\n <Checkbox checked={props.selectedPodNames.includes(pod.name)} />\r\n <ListItemText primary={pod.name} />\r\n </MenuItem>\r\n )\r\n })\r\n }\r\n </Select>\r\n </FormControl>\r\n </Grid>\r\n <Grid item xs={6}>\r\n <FormControl size='small' fullWidth>\r\n <Select value={props.selectedContainerNames} multiple onChange={onContainerNameChange} renderValue={(selected) => (selected as string[]).join(', ')} disabled={props.disabled || props.selectedPodNames.length===0 || getContainerList().length===1}>\r\n {\r\n getContainerList().map(container => {\r\n return (\r\n <MenuItem key={container} value={container}>\r\n <Checkbox checked={props.selectedContainerNames.includes(container)} />\r\n <ListItemText primary={container} />\r\n </MenuItem>\r\n )\r\n })\r\n }\r\n </Select>\r\n </FormControl>\r\n </Grid>\r\n </Grid>\r\n </Grid>\r\n )\r\n}\r\n\r\nexport { ObjectSelector }"],"names":["pods","p"],"mappings":"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"}
1
+ {"version":3,"file":"ObjectSelector.esm.js","sources":["../../../src/components/ObjectSelector/ObjectSelector.tsx"],"sourcesContent":["import React, { useState } from 'react'\r\nimport { ClusterValidPods } from '@jfvilas/plugin-kwirth-common'\r\nimport FormControl from '@material-ui/core/FormControl'\r\nimport Select from '@material-ui/core/Select'\r\nimport MenuItem from '@material-ui/core/MenuItem'\r\nimport { Checkbox, Chip, Grid, ListItemText } from '@material-ui/core'\r\nimport { InstanceConfigScopeEnum, parseResources } from '@jfvilas/kwirth-common'\r\n\r\ninterface IProps {\r\n onSelect: (namespaces:string[], podNames:string[], containerNames:string[]) => void,\r\n cluster: ClusterValidPods,\r\n selectedNamespaces: string[],\r\n selectedPodNames: string[],\r\n selectedContainerNames: string[],\r\n disabled: boolean\r\n}\r\n\r\nconst ObjectSelector = (props: IProps) => {\r\n const [render, setRender] = useState(false)\r\n let pods = props.cluster.data\r\n let namespaceList = Array.from(new Set(pods.map(p => p.namespace)))\r\n\r\n const onNamespaceChange = (namespace:string) => {\r\n let i = props.selectedNamespaces.indexOf(namespace)\r\n if (i>=0)\r\n props.selectedNamespaces.splice(i,1)\r\n else\r\n props.selectedNamespaces.push(namespace)\r\n\r\n props.selectedPodNames.splice(0,props.selectedPodNames.length)\r\n let pods = getPodList()\r\n if (pods.length===1) props.selectedPodNames.push( ...pods.map(p => p.name) )\r\n\r\n props.selectedContainerNames.splice(0,props.selectedContainerNames.length)\r\n let containers = getContainerList()\r\n if (containers.length===1) {\r\n props.selectedContainerNames.push(...containers)\r\n props.onSelect([...props.selectedNamespaces], [...props.selectedPodNames], [...props.selectedContainerNames])\r\n }\r\n\r\n setRender(!render)\r\n };\r\n\r\n const onPodNameChange = (event : any) => {\r\n props.selectedPodNames.splice(0,props.selectedPodNames.length)\r\n props.selectedPodNames.push( ...event.target.value )\r\n\r\n props.selectedContainerNames.splice(0,props.selectedContainerNames.length)\r\n let containers = getContainerList()\r\n if (containers.length===1) props.selectedContainerNames.push(...containers)\r\n\r\n props.onSelect([...props.selectedNamespaces], [...props.selectedPodNames], [...props.selectedContainerNames])\r\n\r\n setRender(!render)\r\n };\r\n\r\n const onContainerNameChange = (event : any) => {\r\n props.selectedContainerNames.splice(0,props.selectedContainerNames.length)\r\n props.selectedContainerNames.push( ...event.target.value )\r\n props.onSelect([...props.selectedNamespaces], [...props.selectedPodNames], [...props.selectedContainerNames])\r\n };\r\n\r\n const existAccessKey = (namespace:string) => {\r\n if (!props.cluster.accessKeys.has(InstanceConfigScopeEnum.VIEW)) return false\r\n let accessKey = props.cluster.accessKeys.get(InstanceConfigScopeEnum.VIEW)\r\n if (accessKey) {\r\n let resources = parseResources(accessKey.resources)\r\n return (resources.find(resource => resource.namespaces === namespace))\r\n }\r\n else return false\r\n\r\n }\r\n\r\n const getPodList = () => {\r\n return Array.from(pods.filter(m => props.selectedNamespaces.includes(m.namespace)))\r\n }\r\n\r\n const getContainerList = () => {\r\n if (props.selectedNamespaces.length===0 || props.selectedPodNames.length===0) return []\r\n let validpods = pods.filter(pod => props.selectedNamespaces.includes(pod.namespace))\r\n validpods = validpods.filter(p => props.selectedPodNames.includes(p.name))\r\n let validcontainers:string[] = []\r\n for (var p of validpods) {\r\n validcontainers.push ( ...p.containers )\r\n }\r\n return Array.from(new Set(validcontainers))\r\n }\r\n\r\n return (\r\n <Grid container direction='column' spacing={0} style={{marginBottom:6, width:'100%'}}>\r\n <Grid item>\r\n {\r\n namespaceList.map ((ns,index) => {\r\n if (props.disabled) {\r\n if (existAccessKey(ns))\r\n return <Chip component={'span'} key={index} label={ns as string} variant={props.selectedNamespaces.includes(ns)?'default':'outlined'} size='small' color='default' />\r\n else\r\n return <Chip component={'span'} key={index} label={ns as string} size='small' color='default' variant={'outlined'}/>\r\n }\r\n else {\r\n if (existAccessKey(ns))\r\n return <Chip component={'span'} key={index} label={ns as string} onClick={() => onNamespaceChange(ns)} variant={props.selectedNamespaces.includes(ns)?'default':'outlined'} size='small' color='primary' />\r\n else\r\n return <Chip component={'span'} key={index} label={ns as string} size='small' color='secondary' variant={'outlined'}/>\r\n }\r\n })\r\n }\r\n </Grid>\r\n <Grid container item xs={12} spacing={2}>\r\n <Grid item xs={6}>\r\n <FormControl size='small' fullWidth>\r\n <Select value={props.selectedPodNames} MenuProps={{variant:'menu'}} multiple onChange={onPodNameChange} renderValue={(selected) => (selected as string[]).join(', ')} disabled={props.disabled || props.selectedNamespaces.length===0 || getPodList().length===1}>\r\n {\r\n getPodList().map(pod => {\r\n return (\r\n <MenuItem key={pod.name} value={pod.name}>\r\n <Checkbox checked={props.selectedPodNames.includes(pod.name)} />\r\n <ListItemText primary={pod.name} />\r\n </MenuItem>\r\n )\r\n })\r\n }\r\n </Select>\r\n </FormControl>\r\n </Grid>\r\n <Grid item xs={6}>\r\n <FormControl size='small' fullWidth>\r\n <Select value={props.selectedContainerNames} MenuProps={{variant:'menu'}} multiple onChange={onContainerNameChange} renderValue={(selected) => (selected as string[]).join(', ')} disabled={props.disabled || props.selectedPodNames.length===0 || getContainerList().length===1}>\r\n {\r\n getContainerList().map(container => {\r\n return (\r\n <MenuItem key={container} value={container}>\r\n <Checkbox checked={props.selectedContainerNames.includes(container)} />\r\n <ListItemText primary={container} />\r\n </MenuItem>\r\n )\r\n })\r\n }\r\n </Select>\r\n </FormControl>\r\n </Grid>\r\n </Grid>\r\n </Grid>\r\n )\r\n}\r\n\r\nexport { ObjectSelector }"],"names":["pods","p"],"mappings":"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"}
@@ -3,7 +3,7 @@ import { Dialog, DialogTitle, DialogContent, Typography, DialogActions, Button }
3
3
  import { InstanceMessageTypeEnum } from '@jfvilas/kwirth-common';
4
4
 
5
5
  const StatusLog = (props) => {
6
- return /* @__PURE__ */ React.createElement(Dialog, { open: true }, /* @__PURE__ */ React.createElement(DialogTitle, null, "Stauts: ", props.level), /* @__PURE__ */ React.createElement(DialogContent, null, props.statusMessages.filter((m) => m.type === InstanceMessageTypeEnum.SIGNAL && m.level === props.level).map((m, index) => /* @__PURE__ */ React.createElement(Typography, { key: index }, m.timestamp?.toISOString(), "\xA0\xA0\xA0\xA0", m.text))), /* @__PURE__ */ React.createElement(DialogActions, null, /* @__PURE__ */ React.createElement(Button, { onClick: () => props.onClear(props.level), color: "primary", variant: "contained" }, "Clear"), /* @__PURE__ */ React.createElement(Button, { onClick: props.onClose, color: "primary", variant: "contained" }, "Close")));
6
+ return /* @__PURE__ */ React.createElement(Dialog, { open: true }, /* @__PURE__ */ React.createElement(DialogTitle, null, "Stauts: ", props.level), /* @__PURE__ */ React.createElement(DialogContent, null, props.statusMessages.filter((m) => m.type === InstanceMessageTypeEnum.SIGNAL && m.level === props.level).map((m, index) => /* @__PURE__ */ React.createElement(Typography, { key: index }, m.text))), /* @__PURE__ */ React.createElement(DialogActions, null, /* @__PURE__ */ React.createElement(Button, { onClick: () => props.onClear(props.level), color: "primary", variant: "contained" }, "Clear"), /* @__PURE__ */ React.createElement(Button, { onClick: props.onClose, color: "primary", variant: "contained" }, "Close")));
7
7
  };
8
8
 
9
9
  export { StatusLog };
@@ -1 +1 @@
1
- {"version":3,"file":"StatusLog.esm.js","sources":["../../../src/components/StatusLog/StatusLog.tsx"],"sourcesContent":["import React from 'react';\r\nimport { Dialog, DialogTitle, DialogContent, DialogActions, Button, Typography } from '@material-ui/core'\r\nimport { InstanceMessageTypeEnum, SignalMessage, SignalMessageLevelEnum } from '@jfvilas/kwirth-common'\r\n\r\nconst StatusLog = (props:{\r\n level: SignalMessageLevelEnum\r\n statusMessages: SignalMessage[]\r\n onClear: (level:SignalMessageLevelEnum) => void\r\n onClose: () => void\r\n }) => {\r\n\r\n return (\r\n <Dialog open={true}>\r\n <DialogTitle>\r\n Stauts: {props.level} \r\n </DialogTitle>\r\n <DialogContent>\r\n { props.statusMessages.filter(m => m.type === InstanceMessageTypeEnum.SIGNAL && m.level === props.level).map( (m,index) => <Typography key={index}>{m.timestamp?.toISOString()}&nbsp;&nbsp;&nbsp;&nbsp;{m.text}</Typography>) }\r\n </DialogContent>\r\n <DialogActions>\r\n <Button onClick={() => props.onClear(props.level)} color='primary' variant='contained'>Clear</Button>\r\n <Button onClick={props.onClose} color='primary' variant='contained'>Close</Button>\r\n </DialogActions>\r\n </Dialog>\r\n )\r\n\r\n}\r\n\r\nexport { StatusLog }"],"names":[],"mappings":";;;;AAIM,MAAA,SAAA,GAAY,CAAC,KAKT,KAAA;AAEN,EAAA,uBACK,KAAA,CAAA,aAAA,CAAA,MAAA,EAAA,EAAO,IAAM,EAAA,IAAA,EAAA,sCACT,WAAY,EAAA,IAAA,EAAA,UAAA,EACA,KAAM,CAAA,KACnB,CACA,kBAAA,KAAA,CAAA,aAAA,CAAC,aACK,EAAA,IAAA,EAAA,KAAA,CAAM,eAAe,MAAO,CAAA,CAAA,CAAA,KAAK,CAAE,CAAA,IAAA,KAAS,uBAAwB,CAAA,MAAA,IAAU,CAAE,CAAA,KAAA,KAAU,MAAM,KAAK,CAAA,CAAE,GAAK,CAAA,CAAC,GAAE,KAAU,qBAAA,KAAA,CAAA,aAAA,CAAC,UAAW,EAAA,EAAA,GAAA,EAAK,SAAQ,CAAE,CAAA,SAAA,EAAW,WAAY,EAAA,EAAE,kBAAyB,EAAA,CAAA,CAAE,IAAK,CAAa,CAChO,CACA,kBAAA,KAAA,CAAA,aAAA,CAAC,aACG,EAAA,IAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,UAAO,OAAS,EAAA,MAAM,KAAM,CAAA,OAAA,CAAQ,MAAM,KAAK,CAAA,EAAG,KAAM,EAAA,SAAA,EAAU,OAAQ,EAAA,WAAA,EAAA,EAAY,OAAK,CAAA,sCAC3F,MAAO,EAAA,EAAA,OAAA,EAAS,KAAM,CAAA,OAAA,EAAS,OAAM,SAAU,EAAA,OAAA,EAAQ,WAAY,EAAA,EAAA,OAAK,CAC7E,CACJ,CAAA;AAGR;;;;"}
1
+ {"version":3,"file":"StatusLog.esm.js","sources":["../../../src/components/StatusLog/StatusLog.tsx"],"sourcesContent":["import React from 'react';\r\nimport { Dialog, DialogTitle, DialogContent, DialogActions, Button, Typography } from '@material-ui/core'\r\nimport { InstanceMessageTypeEnum, SignalMessageLevelEnum } from '@jfvilas/kwirth-common'\r\nimport { IStatusLine } from '@jfvilas/plugin-kwirth-common';\r\n\r\ninterface IProps {\r\n level: SignalMessageLevelEnum\r\n statusMessages: IStatusLine[]\r\n onClear: (level:SignalMessageLevelEnum) => void\r\n onClose: () => void\r\n}\r\n\r\nconst StatusLog = (props:IProps) => {\r\n return (\r\n <Dialog open={true}>\r\n <DialogTitle>\r\n Stauts: {props.level} \r\n </DialogTitle>\r\n <DialogContent>\r\n { props.statusMessages.filter(m => m.type === InstanceMessageTypeEnum.SIGNAL && m.level === props.level).map( (m,index) => <Typography key={index}>{m.text}</Typography>) }\r\n </DialogContent>\r\n <DialogActions>\r\n <Button onClick={() => props.onClear(props.level)} color='primary' variant='contained'>Clear</Button>\r\n <Button onClick={props.onClose} color='primary' variant='contained'>Close</Button>\r\n </DialogActions>\r\n </Dialog>\r\n )\r\n\r\n}\r\n\r\nexport { StatusLog }"],"names":[],"mappings":";;;;AAYM,MAAA,SAAA,GAAY,CAAC,KAAiB,KAAA;AAChC,EAAA,uBACK,KAAA,CAAA,aAAA,CAAA,MAAA,EAAA,EAAO,IAAM,EAAA,IAAA,EAAA,kBACT,KAAA,CAAA,aAAA,CAAA,WAAA,EAAA,IAAA,EAAY,UACA,EAAA,KAAA,CAAM,KACnB,CAAA,kBACC,KAAA,CAAA,aAAA,CAAA,aAAA,EAAA,IAAA,EACK,MAAM,cAAe,CAAA,MAAA,CAAO,CAAK,CAAA,KAAA,CAAA,CAAE,IAAS,KAAA,uBAAA,CAAwB,MAAU,IAAA,CAAA,CAAE,UAAU,KAAM,CAAA,KAAK,CAAE,CAAA,GAAA,CAAK,CAAC,CAAA,EAAE,KAAU,qBAAA,KAAA,CAAA,aAAA,CAAC,cAAW,GAAK,EAAA,KAAA,EAAA,EAAQ,CAAE,CAAA,IAAK,CAAa,CAC5K,CACA,kBAAA,KAAA,CAAA,aAAA,CAAC,aACG,EAAA,IAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,MAAO,EAAA,EAAA,OAAA,EAAS,MAAM,KAAA,CAAM,OAAQ,CAAA,KAAA,CAAM,KAAK,CAAG,EAAA,KAAA,EAAM,SAAU,EAAA,OAAA,EAAQ,WAAY,EAAA,EAAA,OAAK,CAC5F,kBAAA,KAAA,CAAA,aAAA,CAAC,UAAO,OAAS,EAAA,KAAA,CAAM,OAAS,EAAA,KAAA,EAAM,SAAU,EAAA,OAAA,EAAQ,WAAY,EAAA,EAAA,OAAK,CAC7E,CACJ,CAAA;AAGR;;;;"}
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ /// <reference types="react" />
1
2
  import * as react from 'react';
2
3
  import * as _backstage_core_plugin_api from '@backstage/core-plugin-api';
3
4
  import { DiscoveryApi, FetchApi } from '@backstage/core-plugin-api';
@@ -8,7 +9,9 @@ import { ClusterValidPods } from '@jfvilas/plugin-kwirth-common';
8
9
  declare const kwirthLogPlugin: _backstage_core_plugin_api.BackstagePlugin<{
9
10
  root: _backstage_core_plugin_api.RouteRef<undefined>;
10
11
  }, {}, {}>;
11
- declare const EntityKwirthLogContent: () => react.JSX.Element;
12
+ declare const EntityKwirthLogContent: (props: {
13
+ enableRestart: boolean;
14
+ }) => react.JSX.Element;
12
15
 
13
16
  interface KwirthLogApi {
14
17
  getResources(entity: Entity): Promise<any>;
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.esm.js","sources":["../src/plugin.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 { kwirthLogApiRef, KwirthLogClient } from './api';\r\nimport { createApiFactory, createPlugin, createRoutableExtension } from '@backstage/core-plugin-api';\r\nimport { discoveryApiRef, fetchApiRef } from '@backstage/core-plugin-api';\r\nimport { rootRouteRef } from './routes';\r\n\r\nexport const kwirthLogPlugin = createPlugin({\r\n id: 'kwirthlog', \r\n apis: [\r\n createApiFactory({\r\n api: kwirthLogApiRef,\r\n deps: {\r\n discoveryApi: discoveryApiRef,\r\n fetchApi: fetchApiRef,\r\n },\r\n factory({ discoveryApi, fetchApi }) {\r\n return new KwirthLogClient({ discoveryApi, fetchApi });\r\n },\r\n }),\r\n ],\r\n routes: {\r\n root: rootRouteRef\r\n }\r\n});\r\n\r\nexport const EntityKwirthLogContent = kwirthLogPlugin.provide(\r\n createRoutableExtension({\r\n name: 'EntityKwirthLogContent',\r\n component: () =>\r\n import('./components/EntityKwirthLogContent').then(m => m.EntityKwirthLogContent),\r\n mountPoint: rootRouteRef\r\n })\r\n);\r\n"],"names":[],"mappings":";;;;;AAoBO,MAAM,kBAAkB,YAAa,CAAA;AAAA,EAC1C,EAAI,EAAA,WAAA;AAAA,EACJ,IAAM,EAAA;AAAA,IACJ,gBAAiB,CAAA;AAAA,MACf,GAAK,EAAA,eAAA;AAAA,MACL,IAAM,EAAA;AAAA,QACJ,YAAc,EAAA,eAAA;AAAA,QACd,QAAU,EAAA;AAAA,OACZ;AAAA,MACA,OAAQ,CAAA,EAAE,YAAc,EAAA,QAAA,EAAY,EAAA;AAClC,QAAA,OAAO,IAAI,eAAA,CAAgB,EAAE,YAAA,EAAc,UAAU,CAAA;AAAA;AACvD,KACD;AAAA,GACH;AAAA,EACA,MAAQ,EAAA;AAAA,IACN,IAAM,EAAA;AAAA;AAEV,CAAC;AAEM,MAAM,yBAAyB,eAAgB,CAAA,OAAA;AAAA,EACpD,uBAAwB,CAAA;AAAA,IACtB,IAAM,EAAA,wBAAA;AAAA,IACN,SAAA,EAAW,MACT,OAAO,kDAAqC,EAAE,IAAK,CAAA,CAAA,CAAA,KAAK,EAAE,sBAAsB,CAAA;AAAA,IAClF,UAAY,EAAA;AAAA,GACb;AACH;;;;"}
1
+ {"version":3,"file":"plugin.esm.js","sources":["../src/plugin.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\n\r\nimport { kwirthLogApiRef, KwirthLogClient } from './api';\r\nimport { createApiFactory, createPlugin, createRoutableExtension } from '@backstage/core-plugin-api';\r\nimport { discoveryApiRef, fetchApiRef } from '@backstage/core-plugin-api';\r\nimport { rootRouteRef } from './routes';\r\n\r\nexport const kwirthLogPlugin = createPlugin({\r\n id: 'kwirthlog', \r\n apis: [\r\n createApiFactory({\r\n api: kwirthLogApiRef,\r\n deps: {\r\n discoveryApi: discoveryApiRef,\r\n fetchApi: fetchApiRef,\r\n },\r\n factory({ discoveryApi, fetchApi }) {\r\n return new KwirthLogClient({ discoveryApi, fetchApi });\r\n },\r\n }),\r\n ],\r\n routes: {\r\n root: rootRouteRef\r\n }\r\n})\r\n\r\nexport const EntityKwirthLogContent = kwirthLogPlugin.provide(\r\n createRoutableExtension({\r\n name: 'EntityKwirthLogContent',\r\n component: () =>\r\n import('./components/EntityKwirthLogContent').then(m => m.EntityKwirthLogContent),\r\n mountPoint: rootRouteRef\r\n })\r\n)\r\n"],"names":[],"mappings":";;;;;AAqBO,MAAM,kBAAkB,YAAa,CAAA;AAAA,EAC1C,EAAI,EAAA,WAAA;AAAA,EACJ,IAAM,EAAA;AAAA,IACJ,gBAAiB,CAAA;AAAA,MACf,GAAK,EAAA,eAAA;AAAA,MACL,IAAM,EAAA;AAAA,QACJ,YAAc,EAAA,eAAA;AAAA,QACd,QAAU,EAAA;AAAA,OACZ;AAAA,MACA,OAAQ,CAAA,EAAE,YAAc,EAAA,QAAA,EAAY,EAAA;AAClC,QAAA,OAAO,IAAI,eAAA,CAAgB,EAAE,YAAA,EAAc,UAAU,CAAA;AAAA;AACvD,KACD;AAAA,GACH;AAAA,EACA,MAAQ,EAAA;AAAA,IACN,IAAM,EAAA;AAAA;AAEV,CAAC;AAEM,MAAM,yBAAyB,eAAgB,CAAA,OAAA;AAAA,EACpD,uBAAwB,CAAA;AAAA,IACtB,IAAM,EAAA,wBAAA;AAAA,IACN,SAAA,EAAW,MACT,OAAO,kDAAqC,EAAE,IAAK,CAAA,CAAA,CAAA,KAAK,EAAE,sBAAsB,CAAA;AAAA,IAClF,UAAY,EAAA;AAAA,GACb;AACH;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jfvilas/plugin-kwirth-log",
3
- "version": "0.12.4",
3
+ "version": "0.12.6",
4
4
  "description": "Frontend plugin for viewing real-time Kubernetes logs in Backstage",
5
5
  "keywords": [
6
6
  "Backstage",
@@ -63,7 +63,6 @@
63
63
  "@backstage/integration-react": "^1.1.29",
64
64
  "@backstage/plugin-auth-react": "^0.1.4",
65
65
  "@backstage/plugin-catalog-react": "^1.12.2",
66
- "@jfvilas/kwirth-common": "^0.3.55",
67
66
  "@material-ui/core": "^4.12.2",
68
67
  "@material-ui/icons": "^4.9.1",
69
68
  "@types/react": "^16.13.1 || ^17.0.0 || ^18.0.0",
@@ -1,20 +0,0 @@
1
- import React from 'react';
2
- import IconButton from '@material-ui/core/IconButton';
3
- import Snackbar from '@material-ui/core/Snackbar';
4
- import CloseIcon from '@material-ui/icons/Close';
5
-
6
- const ShowError = (props) => {
7
- return /* @__PURE__ */ React.createElement(
8
- Snackbar,
9
- {
10
- message: `An error has ocurred: ${props.message}`,
11
- open: true,
12
- autoHideDuration: 3e3,
13
- anchorOrigin: { vertical: "top", horizontal: "center" },
14
- action: /* @__PURE__ */ React.createElement(IconButton, { size: "small", "aria-label": "close", color: "inherit", onClick: props.onClose }, /* @__PURE__ */ React.createElement(CloseIcon, { fontSize: "small" }))
15
- }
16
- );
17
- };
18
-
19
- export { ShowError };
20
- //# sourceMappingURL=ShowError.esm.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ShowError.esm.js","sources":["../../../src/components/ShowError/ShowError.tsx"],"sourcesContent":["import React from 'react'\r\nimport IconButton from '@material-ui/core/IconButton'\r\nimport Snackbar from '@material-ui/core/Snackbar'\r\nimport CloseIcon from '@material-ui/icons/Close'\r\n\r\nconst ShowError = (props: {\r\n message: string\r\n onClose:() => void\r\n }) => {\r\n\r\n return (\r\n <Snackbar \r\n message={`An error has ocurred: ${props.message}`}\r\n open={true}\r\n autoHideDuration={3000}\r\n anchorOrigin={{ vertical:'top', horizontal:'center' }}\r\n action={ \r\n <IconButton size=\"small\" aria-label=\"close\" color=\"inherit\" onClick={props.onClose}>\r\n <CloseIcon fontSize=\"small\" />\r\n </IconButton>\r\n }>\r\n </Snackbar>\r\n )\r\n}\r\n\r\nexport { ShowError }"],"names":[],"mappings":";;;;;AAKM,MAAA,SAAA,GAAY,CAAC,KAGT,KAAA;AAEN,EACI,uBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACG,OAAA,EAAS,CAAyB,sBAAA,EAAA,KAAA,CAAM,OAAO,CAAA,CAAA;AAAA,MAC/C,IAAM,EAAA,IAAA;AAAA,MACN,gBAAkB,EAAA,GAAA;AAAA,MAClB,YAAc,EAAA,EAAE,QAAS,EAAA,KAAA,EAAO,YAAW,QAAS,EAAA;AAAA,MACpD,wBACK,KAAA,CAAA,aAAA,CAAA,UAAA,EAAA,EAAW,IAAK,EAAA,OAAA,EAAQ,cAAW,OAAQ,EAAA,KAAA,EAAM,SAAU,EAAA,OAAA,EAAS,MAAM,OACvE,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,SAAU,EAAA,EAAA,QAAA,EAAS,SAAQ,CAChC;AAAA;AAAA,GAER;AAER;;;;"}