@jfvilas/plugin-kwirth-fileman 0.13.10 → 0.14.2

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,14 +1,14 @@
1
1
  # Backstage frontend KwirthFileman plugin
2
- This package is a Backstage frontend plugin for **managing Kubernetes containers' filesystems** in real-time via Kwirth.
2
+ This package is a Backstage frontend plugin for **managing Kubernetes containers' filesystems visually** in real-time via Kwirth.
3
3
 
4
- This Backstage plugin allows you to use a file-explorer-like plugin for navigating through the filesystem, allowing users to examine the content, and also perform file operations like rename, delete, copy, move, copy/cut/paste...
4
+ KwirthFileman plugin allows you to use a file-explorer-like plugin for navigating through the filesystem, allowing users to examine the content, and also perform file operations like rename, delete, copy, move, copy/cut/paste...
5
5
 
6
6
  In addtion users can also download files (or folders), upload files and even preview file content.
7
7
 
8
8
  - You need to install the Kwirth [Backstage backend plugin](https://www.npmjs.com/package/@jfvilas/plugin-kwirth-backend).
9
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).
10
10
 
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.
11
+ Kwirth is a really-easy-to-use data-exporting system for Kubernetes that runs in only one pod (*no database is needed*), in your Desktop with a GUI or in a Docker container. 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.
12
12
 
13
13
  You can access [Kwirth project here](https://github.com/jfvilas/kwirth).
14
14
 
@@ -18,22 +18,22 @@ Following table shows version compatibility between this Kwirth Backstage plugin
18
18
 
19
19
  | Plugin Kwirth version | Kwirth version |
20
20
  |-|-|
21
- |0.13.5|0.4.131|
21
+ |0.14.1|0.5.21|
22
22
 
23
23
 
24
24
  ## What is this plugin for?
25
- This Backstage plugin adds Backstage a feature for working with Kubernetes containers filesystems and manage container data as user would do with a Gnome, the Windows file explorer or an Apple file manager.
25
+ This Backstage plugin adds Backstage a powerful feature for working with Kubernetes containers' filesystems and manage container data as users would do with a Gnome, the Windows file explorer or an Apple file manager.
26
26
 
27
27
  When KwirthFileman is correctly installed and configured, it is possible to manage Kubernetes containers filesystems like this:
28
28
 
29
29
  ![kwirth-running](https://raw.githubusercontent.com/jfvilas/plugin-kwirth-fileman/master/images/kwirthfileman-running.png)
30
30
 
31
- This frontend plugin includes just the visualization of filesystems. All needed configuration, and specially **permission settings**, are done in the backend plugin and the app-config.yaml. You can restrict access to pods, namespaces, clusters, etc... by configuring permissions to be applied on the backend plugin.
31
+ This frontend plugin includes the visualization of filesystems. All needed configuration, and specially **permission settings**, are done in the backend plugin and the app-config.yaml. You can restrict access to pods, namespaces, clusters, containers, etc... by configuring permissions to be applied on the backend plugin.
32
32
 
33
33
  ## How does it work?
34
34
  Let's explain this by following a user working sequence:
35
35
 
36
- 1. A Backstage user searchs for an entity in the Backstage.
36
+ 1. A Backstage user searchs for an entity in the Backstage instance.
37
37
  2. In the entity page there will be a new tab named 'KWIRTHFILEMAN'.
38
38
  3. When the user clicks on KWIRTHFILEMAN the frontend plugin sends a request to the backend Kwirth plugin asking for containers information on all Kubernetes clusters available.
39
39
  4. Next step is to identify the Kubernetes objects that match requested entity. As well as it occurs with other Backstage Kwirth plugins, Kwirth implements two strategies for getting the list of kubernetes objects that match:
@@ -43,7 +43,7 @@ Let's explain this by following a user working sequence:
43
43
  6. With the final pod list, the backend plugin sends requests to the Kwirth instances on the clusters asking for API Keys specific for accessing containers filesystems.
44
44
  7. With all this information, the backend builds a unique response containing all the pods the user have access to, and all the API keys needed to access the filesystems.
45
45
 
46
- If everyting is correctly configured and tagged, the user should see a list of clusters. When selecting a cluster, the user should see a control for starting and stoppingthe file system browser. When th euser clicks PLAY (on the right upper side), the file browser appears.
46
+ If everyting is correctly configured and tagged, the user should see a list of clusters. When selecting a cluster, the user should see a control for starting and stopping the file system browser. When the user clicks PLAY (on the right upper side), the file browser appears.
47
47
 
48
48
 
49
49
  ## Installation
@@ -51,22 +51,19 @@ It's very simple and straightforward, it is in fact very similar to any other fr
51
51
 
52
52
  1. Install corresponding Backstage backend plugin [more information here](https://www.npmjs.com/package/@jfvilas/plugin-kwirth-backend).
53
53
  2. Install this Backstage frontend plugin:
54
-
55
- ```sh
56
- # From your Backstage root directory
57
- yarn --cwd packages/app add @jfvilas/plugin-kwirth-fileman @jfvilas/plugin-kwirth-frontend @jfvilas/plugin-kwirth-common @jfvilas/kwirth-common
58
- ```
59
-
54
+ ```sh
55
+ # From your Backstage root directory
56
+ yarn --cwd packages/app add @jfvilas/plugin-kwirth-fileman @jfvilas/plugin-kwirth-frontend @jfvilas/plugin-kwirth-common @jfvilas/kwirth-common
57
+ ```
60
58
  3. Make sure the [Kwirth backend plugin](https://www.npmjs.com/package/@jfvilas/plugin-kwirth-backend#configure) is installed and configured.
61
-
62
59
  4. Restart your Backstage instance.
63
60
 
64
61
 
65
62
  ## Configuration: Entity Pages
66
63
  For Kwirth plugin to be usable on the frontend, you must tailor your Entity Page to include the Kwirth components.
67
64
 
68
- #### 1. Add the plugin as a tab in your Entity pages:
69
65
 
66
+ #### 1. Add the plugin as a tab in your Entity pages:
70
67
  Firstly, import the plugin module.
71
68
 
72
69
  ```typescript
@@ -109,11 +106,11 @@ Use one of these strategies:
109
106
 
110
107
  - **Strategy 1: one-to-one**. Add `backstage.io/kubernetes-id` annotation to your `catalog-info.yaml` for the entities deployed to Kubernetes you want to work with on Backstage. This is the same annotation that the Kubernetes core plugin uses, so, maybe you already have added it to your components. Exmaple:
111
108
 
112
- ```yaml
113
- metadata:
114
- annotations:
115
- backstage.io/kubernetes-id: entity001
116
- ```
109
+ ```yaml
110
+ metadata:
111
+ annotations:
112
+ backstage.io/kubernetes-id: entity001
113
+ ```
117
114
 
118
115
  - **Strategy 2: use selectors**. Add `backstage.io/kubernetes-label-selector` annotation to your `catalog-info.yaml` for the entities you want to work with. This is the same annotation that the Kubernetes core plugin uses, so, maybe you already have added it to your components. The label selector value follows Kubernetes [label selector semantics](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/). Example:
119
116
 
@@ -6,7 +6,7 @@ import { useApi, alertApiRef } from '@backstage/core-plugin-api';
6
6
  import { isKwirthAvailable, ANNOTATION_BACKSTAGE_KUBERNETES_LABELID, ANNOTATION_BACKSTAGE_KUBERNETES_LABELSELECTOR, getPodList, getContainerList } from '@jfvilas/plugin-kwirth-common';
7
7
  import { useEntity, MissingAnnotationEmptyState } from '@backstage/plugin-catalog-react';
8
8
  import { kwirthFilemanApiRef } from '../api/types.esm.js';
9
- import { SignalMessageLevelEnum, accessKeySerialize, InstanceMessageTypeEnum, InstanceMessageActionEnum, InstanceMessageFlowEnum, InstanceConfigViewEnum, InstanceConfigObjectEnum, SignalMessageEventEnum } from '@jfvilas/kwirth-common';
9
+ import { ESignalMessageLevel, accessKeySerialize, EInstanceMessageType, EInstanceMessageAction, EInstanceMessageFlow, EInstanceConfigView, EInstanceConfigObject, ESignalMessageEvent } from '@jfvilas/kwirth-common';
10
10
  import { ComponentNotFound, ErrorType, ClusterList, KwirthNews, StatusLog } from '@jfvilas/plugin-kwirth-frontend';
11
11
  import { FileManager } from '@jfvilas/react-file-manager';
12
12
  import { VERSION } from '../version.esm.js';
@@ -48,7 +48,7 @@ const EntityKwirthFilemanContent = (props) => {
48
48
  const [statusMessages, setStatusMessages] = useState([]);
49
49
  const [webSocket, setWebSocket] = useState();
50
50
  const [showStatusDialog, setShowStatusDialog] = useState(false);
51
- const [statusLevel, setStatusLevel] = useState(SignalMessageLevelEnum.INFO);
51
+ const [statusLevel, setStatusLevel] = useState(ESignalMessageLevel.INFO);
52
52
  const [backendVersion, setBackendVersion] = useState("");
53
53
  const [backendInfo, setBackendInfo] = useState();
54
54
  const instance = useRef();
@@ -64,6 +64,7 @@ const EntityKwirthFilemanContent = (props) => {
64
64
  });
65
65
  const filemanBoxRef = useRef(null);
66
66
  const [filemanBoxTop, setFilemanBoxTop] = useState(0);
67
+ const [runningInstance, setRunningInstance] = useState();
67
68
  let permissions = {
68
69
  create: true,
69
70
  delete: true,
@@ -85,7 +86,7 @@ const EntityKwirthFilemanContent = (props) => {
85
86
  let accessKey = cluster.accessKeys.get("fileman$read");
86
87
  if (accessKey) {
87
88
  fileUploadConfig = {
88
- url: `${cluster.url}/channel/fileman/upload?key=${instance.current}`,
89
+ url: `${cluster.url}/${runningInstance}/channel/fileman/upload?key=${instance.current}`,
89
90
  method: "POST",
90
91
  headers: {
91
92
  "Authorization": "Bearer " + accessKeySerialize(accessKey)
@@ -165,27 +166,26 @@ const EntityKwirthFilemanContent = (props) => {
165
166
  const processFilemanMessage = (wsEvent) => {
166
167
  let msg = JSON.parse(wsEvent.data);
167
168
  switch (msg.type) {
168
- case InstanceMessageTypeEnum.DATA: {
169
+ case EInstanceMessageType.DATA: {
169
170
  let response = JSON.parse(wsEvent.data);
170
171
  switch (response.action) {
171
- case InstanceMessageActionEnum.COMMAND:
172
+ case EInstanceMessageAction.COMMAND:
172
173
  {
173
174
  switch (response.command) {
174
175
  case "home" /* HOME */:
175
176
  let data = response.data;
176
177
  let nss = Array.from(new Set(data.map((n) => n.split("/")[0])));
177
- nss.map((ns) => {
178
+ nss.forEach((ns) => {
178
179
  if (!files.current.some((f) => f.path === "/" + ns)) {
179
180
  files.current.push({ name: ns, isDirectory: true, path: "/" + ns, class: "namespace" });
180
181
  }
181
182
  let podNames = Array.from(new Set(data.filter((a) => a.split("/")[0] === ns).map((o) => o.split("/")[1])));
182
- podNames.map((p) => {
183
+ podNames.forEach((p) => {
183
184
  if (!files.current.some((f) => f.path === "/" + ns + "/" + p)) {
184
185
  files.current.push({ name: p, isDirectory: true, path: "/" + ns + "/" + p, class: "pod" });
185
186
  }
186
- let containers = Array.from(new Set(data.filter((a) => a.split("/")[0] === ns && a.split("/")[1] === p).map((o) => o.split("/")[2])));
187
- containers = containers.filter((c) => !props.excludeContainers?.includes(c));
188
- containers.map((c) => {
187
+ let conts = Array.from(new Set(data.filter((a) => a.split("/")[0] === ns && a.split("/")[1] === p).map((o) => o.split("/")[2])));
188
+ conts.forEach((c) => {
189
189
  if (!files.current.some((f) => f.path === "/" + ns + "/" + p + "/" + c)) {
190
190
  files.current.push({ name: c, isDirectory: true, path: "/" + ns + "/" + p + "/" + c, class: "container" });
191
191
  }
@@ -197,31 +197,34 @@ const EntityKwirthFilemanContent = (props) => {
197
197
  case "dir" /* DIR */:
198
198
  let content = JSON.parse(response.data);
199
199
  if (content.status === "Success") {
200
- for (let o of content.metadata.object) {
201
- let name = o.name.split("/")[o.name.split("/").length - 1];
202
- let e = {
203
- name,
204
- isDirectory: o.type === 1,
205
- path: o.name,
206
- updatedAt: (/* @__PURE__ */ new Date(+o.time)).toISOString(),
207
- size: +o.size,
208
- ...o.type === 0 ? { class: "file" } : {}
209
- };
210
- let i = files.current.findIndex((f) => f.path === e.path);
211
- if (i >= 0)
212
- files.current[i] = e;
213
- else
200
+ if (content.status !== "Success") {
201
+ addMessage(ESignalMessageLevel.ERROR, content.text || content.message);
202
+ } else {
203
+ for (let o of content.metadata.object) {
204
+ let name = o.name.split("/")[o.name.split("/").length - 1];
205
+ let e = {
206
+ name,
207
+ isDirectory: o.type === 1,
208
+ path: o.name,
209
+ data: {
210
+ updatedAt: (/* @__PURE__ */ new Date(+o.time)).toISOString(),
211
+ size: +o.size,
212
+ ...o.type === 0 ? { class: "file" } : {}
213
+ }
214
+ };
215
+ files.current = files.current.filter((f) => f.path !== e.path);
214
216
  files.current.push(e);
217
+ }
215
218
  }
216
219
  setStateFiles([...files.current]);
217
220
  } else {
218
- addMessage(SignalMessageLevelEnum.ERROR, content.text || content.message);
221
+ addMessage(ESignalMessageLevel.ERROR, content.text || content.message);
219
222
  }
220
223
  break;
221
224
  case "rename" /* RENAME */:
222
225
  {
223
226
  let content2 = JSON.parse(response.data);
224
- if (content2.status !== "Success") addMessage(SignalMessageLevelEnum.ERROR, content2.text || content2.message);
227
+ if (content2.status !== "Success") addMessage(ESignalMessageLevel.ERROR, content2.text || content2.message);
225
228
  }
226
229
  break;
227
230
  case "delete" /* DELETE */: {
@@ -232,7 +235,7 @@ const EntityKwirthFilemanContent = (props) => {
232
235
  files.current = files.current.filter((f) => !f.path.startsWith(fname + "/"));
233
236
  setStateFiles([...files.current]);
234
237
  } else {
235
- addMessage(SignalMessageLevelEnum.ERROR, content2.text || content2.message);
238
+ addMessage(ESignalMessageLevel.ERROR, content2.text || content2.message);
236
239
  }
237
240
  break;
238
241
  }
@@ -241,18 +244,20 @@ const EntityKwirthFilemanContent = (props) => {
241
244
  case "create" /* CREATE */: {
242
245
  let content2 = JSON.parse(response.data);
243
246
  if (content2.status === "Success") {
244
- let f = {
247
+ let e = {
245
248
  name: content2.metadata.object.split("/").slice(-1)[0],
246
249
  isDirectory: content2.metadata.type === 1,
247
250
  path: content2.metadata.object,
248
- updatedAt: (/* @__PURE__ */ new Date(+content2.metadata.time)).toISOString(),
249
- size: +content2.metadata.size,
250
- ...content2.metadata.type.type === 0 ? { class: "file" } : {}
251
+ data: {
252
+ updatedAt: (/* @__PURE__ */ new Date(+content2.metadata.time)).toISOString(),
253
+ size: +content2.metadata.size,
254
+ ...content2.metadata.type.type === 0 ? { class: "file" } : {}
255
+ }
251
256
  };
252
- files.current.push(f);
257
+ files.current.push(e);
253
258
  setStateFiles([...files.current]);
254
259
  } else {
255
- addMessage(SignalMessageLevelEnum.ERROR, content2.text || content2.message);
260
+ addMessage(ESignalMessageLevel.ERROR, content2.text || content2.message);
256
261
  }
257
262
  break;
258
263
  }
@@ -262,26 +267,43 @@ const EntityKwirthFilemanContent = (props) => {
262
267
  }
263
268
  break;
264
269
  }
265
- case InstanceMessageTypeEnum.SIGNAL:
270
+ case EInstanceMessageType.SIGNAL:
266
271
  let signalMessage = JSON.parse(wsEvent.data);
267
- if (signalMessage.flow === InstanceMessageFlowEnum.RESPONSE) {
268
- if (signalMessage.action === InstanceMessageActionEnum.START) {
269
- if (signalMessage.text) addMessage(SignalMessageLevelEnum.INFO, signalMessage.text);
270
- instance.current = signalMessage.instance;
271
- } else {
272
- addMessage(SignalMessageLevelEnum.ERROR, wsEvent.data);
272
+ if (signalMessage.flow === EInstanceMessageFlow.RESPONSE) {
273
+ switch (signalMessage.action) {
274
+ case EInstanceMessageAction.START:
275
+ if (signalMessage.text) addMessage(ESignalMessageLevel.INFO, signalMessage.text);
276
+ instance.current = signalMessage.instance;
277
+ break;
278
+ case EInstanceMessageAction.RI:
279
+ setRunningInstance(signalMessage.data);
280
+ break;
281
+ case EInstanceMessageAction.COMMAND:
282
+ if (signalMessage.text) addMessage(signalMessage.level, signalMessage.text);
283
+ break;
284
+ default:
285
+ addMessage(ESignalMessageLevel.ERROR, wsEvent.data);
286
+ break;
273
287
  }
274
- } else if (signalMessage.flow === InstanceMessageFlowEnum.UNSOLICITED) {
288
+ } else if (signalMessage.flow === EInstanceMessageFlow.UNSOLICITED) {
275
289
  let cluster2 = validClusters.find((cluster3) => cluster3.name === selectedClusterName);
276
290
  if (cluster2) {
277
291
  let accessKey = cluster2.accessKeys.get("fileman$read");
278
292
  if (accessKey && instance?.current) {
279
- if (signalMessage.event === SignalMessageEventEnum.ADD) {
293
+ if (signalMessage.event === ESignalMessageEvent.ADD) {
294
+ let instanceConfig = {
295
+ action: EInstanceMessageAction.RI,
296
+ channel: "fileman",
297
+ flow: EInstanceMessageFlow.REQUEST,
298
+ type: EInstanceMessageType.SIGNAL,
299
+ instance: instance.current
300
+ };
301
+ wsEvent.target.send(JSON.stringify(instanceConfig));
280
302
  let filemanMessage = {
281
- flow: InstanceMessageFlowEnum.REQUEST,
282
- action: InstanceMessageActionEnum.COMMAND,
303
+ flow: EInstanceMessageFlow.REQUEST,
304
+ action: EInstanceMessageAction.COMMAND,
283
305
  channel: "fileman",
284
- type: InstanceMessageTypeEnum.DATA,
306
+ type: EInstanceMessageType.DATA,
285
307
  accessKey: accessKeySerialize(accessKey),
286
308
  instance: instance.current,
287
309
  id: v4(),
@@ -295,13 +317,13 @@ const EntityKwirthFilemanContent = (props) => {
295
317
  };
296
318
  let payload = JSON.stringify(filemanMessage);
297
319
  wsEvent.target.send(payload);
298
- if (signalMessage.text) addMessage(SignalMessageLevelEnum.INFO, signalMessage.text);
320
+ if (signalMessage.text) addMessage(ESignalMessageLevel.INFO, signalMessage.text);
299
321
  }
300
322
  } else {
301
- addMessage(SignalMessageLevelEnum.INFO, "Have no instance/accessKey");
323
+ addMessage(ESignalMessageLevel.INFO, "Have no instance/accessKey");
302
324
  }
303
325
  } else {
304
- addMessage(SignalMessageLevelEnum.INFO, "Have no cluster");
326
+ addMessage(ESignalMessageLevel.INFO, "Have no cluster");
305
327
  }
306
328
  }
307
329
  break;
@@ -312,17 +334,14 @@ const EntityKwirthFilemanContent = (props) => {
312
334
  };
313
335
  const addMessage = (level2, text) => {
314
336
  alertApi.post({ message: text, severity: level2, display: "transient" });
315
- setStatusMessages((prev) => [...prev, {
316
- level: level2,
317
- text,
318
- type: InstanceMessageTypeEnum.SIGNAL
319
- }]);
337
+ setStatusMessages((prev) => [...prev, { level: level2, text, type: EInstanceMessageType.SIGNAL }]);
320
338
  };
321
339
  const websocketOnMessage = (wsEvent) => {
322
340
  let instanceMessage;
323
341
  try {
324
342
  instanceMessage = JSON.parse(wsEvent.data);
325
343
  } catch (err) {
344
+ addMessage(ESignalMessageLevel.ERROR, err);
326
345
  console.log(err);
327
346
  console.log(wsEvent.data);
328
347
  return;
@@ -332,8 +351,8 @@ const EntityKwirthFilemanContent = (props) => {
332
351
  processFilemanMessage(wsEvent);
333
352
  break;
334
353
  default:
335
- addMessage(SignalMessageLevelEnum.ERROR, "Invalid channel in message: " + instanceMessage.channel);
336
- addMessage(SignalMessageLevelEnum.ERROR, "Invalid message: " + JSON.stringify(instanceMessage));
354
+ addMessage(ESignalMessageLevel.ERROR, "Invalid channel in message: " + instanceMessage.channel);
355
+ addMessage(ESignalMessageLevel.ERROR, "Invalid message: " + JSON.stringify(instanceMessage));
337
356
  break;
338
357
  }
339
358
  };
@@ -341,15 +360,14 @@ const EntityKwirthFilemanContent = (props) => {
341
360
  setWebSocket(ws);
342
361
  let cluster2 = validClusters.find((cluster3) => cluster3.name === selectedClusterName);
343
362
  if (!cluster2) {
344
- addMessage(SignalMessageLevelEnum.ERROR, "No cluster selected");
363
+ addMessage(ESignalMessageLevel.ERROR, "No cluster selected");
345
364
  return;
346
365
  }
347
366
  let pods = cluster2.pods.filter((p2) => selectedNamespaces.includes(p2.namespace));
348
367
  if (!pods) {
349
- addMessage(SignalMessageLevelEnum.ERROR, "No pods found");
368
+ addMessage(ESignalMessageLevel.ERROR, "No pods found");
350
369
  return;
351
370
  }
352
- console.log(`WS connected`);
353
371
  let accessKey = cluster2.accessKeys.get("fileman$read");
354
372
  if (accessKey) {
355
373
  let containers = [];
@@ -362,30 +380,30 @@ const EntityKwirthFilemanContent = (props) => {
362
380
  }
363
381
  let iConfig = {
364
382
  channel: "fileman",
365
- objects: InstanceConfigObjectEnum.PODS,
366
- action: InstanceMessageActionEnum.START,
367
- flow: InstanceMessageFlowEnum.REQUEST,
383
+ objects: EInstanceConfigObject.PODS,
384
+ action: EInstanceMessageAction.START,
385
+ flow: EInstanceMessageFlow.REQUEST,
368
386
  instance: "",
369
387
  accessKey: accessKeySerialize(accessKey),
370
388
  scope: "fileman$read",
371
- view: selectedContainerNames.length > 0 ? InstanceConfigViewEnum.CONTAINER : InstanceConfigViewEnum.POD,
389
+ view: selectedContainerNames.length > 0 ? EInstanceConfigView.CONTAINER : EInstanceConfigView.POD,
372
390
  namespace: selectedNamespaces.join(","),
373
391
  group: "",
374
392
  pod: selectedPodNames.map((p2) => p2).join(","),
375
393
  container: containers.join(","),
376
394
  data: {},
377
- type: InstanceMessageTypeEnum.SIGNAL
395
+ type: EInstanceMessageType.SIGNAL
378
396
  };
379
397
  ws.send(JSON.stringify(iConfig));
380
398
  } else {
381
- addMessage(SignalMessageLevelEnum.ERROR, "No accessKey for starting fileman streaming");
399
+ addMessage(ESignalMessageLevel.ERROR, "No accessKey for starting fileman streaming");
382
400
  return;
383
401
  }
384
402
  };
385
403
  const startFilemanViewer = () => {
386
404
  let cluster2 = validClusters.find((cluster3) => cluster3.name === selectedClusterName);
387
405
  if (!cluster2) {
388
- addMessage(SignalMessageLevelEnum.ERROR, "No cluster selected");
406
+ addMessage(ESignalMessageLevel.ERROR, "No cluster selected");
389
407
  return;
390
408
  }
391
409
  try {
@@ -422,14 +440,14 @@ const EntityKwirthFilemanContent = (props) => {
422
440
  const prepareText = (txt) => {
423
441
  return txt ? txt.length > 25 ? txt.substring(0, 25) + "..." : txt : "N/A";
424
442
  };
425
- return /* @__PURE__ */ React.createElement(Grid, { container: true, direction: "row" }, /* @__PURE__ */ React.createElement(Grid, { item: true }, /* @__PURE__ */ React.createElement(Typography, { variant: "h5" }, prepareText(title))), /* @__PURE__ */ React.createElement(Grid, { item: true, style: { marginTop: "-8px" } }, /* @__PURE__ */ React.createElement(IconButton, { title: "info", disabled: !statusMessages.some((m) => m.type === InstanceMessageTypeEnum.SIGNAL && m.level === SignalMessageLevelEnum.INFO), onClick: () => show(SignalMessageLevelEnum.INFO) }, /* @__PURE__ */ React.createElement(InfoIcon, { style: { color: statusMessages.some((m) => m.type === InstanceMessageTypeEnum.SIGNAL && m.level === SignalMessageLevelEnum.INFO) ? "blue" : "#BDBDBD" } })), /* @__PURE__ */ React.createElement(IconButton, { title: "warning", disabled: !statusMessages.some((m) => m.type === InstanceMessageTypeEnum.SIGNAL && m.level === SignalMessageLevelEnum.WARNING), onClick: () => show(SignalMessageLevelEnum.WARNING), style: { marginLeft: "-16px" } }, /* @__PURE__ */ React.createElement(WarningIcon, { style: { color: statusMessages.some((m) => m.type === InstanceMessageTypeEnum.SIGNAL && m.level === SignalMessageLevelEnum.WARNING) ? "orange" : "#BDBDBD" } })), /* @__PURE__ */ React.createElement(IconButton, { title: "error", disabled: !statusMessages.some((m) => m.type === InstanceMessageTypeEnum.SIGNAL && m.level === SignalMessageLevelEnum.ERROR), onClick: () => show(SignalMessageLevelEnum.ERROR), style: { marginLeft: "-16px" } }, /* @__PURE__ */ React.createElement(ErrorIcon, { style: { color: statusMessages.some((m) => m.type === InstanceMessageTypeEnum.SIGNAL && m.level === SignalMessageLevelEnum.ERROR) ? "red" : "#BDBDBD" } }))));
443
+ return /* @__PURE__ */ React.createElement(Grid, { container: true, direction: "row" }, /* @__PURE__ */ React.createElement(Grid, { item: true }, /* @__PURE__ */ React.createElement(Typography, { variant: "h5" }, prepareText(title))), /* @__PURE__ */ React.createElement(Grid, { item: true, style: { marginTop: "-8px" } }, /* @__PURE__ */ React.createElement(IconButton, { title: "info", disabled: !statusMessages.some((m) => m.type === EInstanceMessageType.SIGNAL && m.level === ESignalMessageLevel.INFO), onClick: () => show(ESignalMessageLevel.INFO) }, /* @__PURE__ */ React.createElement(InfoIcon, { style: { color: statusMessages.some((m) => m.type === EInstanceMessageType.SIGNAL && m.level === ESignalMessageLevel.INFO) ? "#1D63ED" : "#BDBDBD" } })), /* @__PURE__ */ React.createElement(IconButton, { title: "warning", disabled: !statusMessages.some((m) => m.type === EInstanceMessageType.SIGNAL && m.level === ESignalMessageLevel.WARNING), onClick: () => show(ESignalMessageLevel.WARNING), style: { marginLeft: "-16px" } }, /* @__PURE__ */ React.createElement(WarningIcon, { style: { color: statusMessages.some((m) => m.type === EInstanceMessageType.SIGNAL && m.level === ESignalMessageLevel.WARNING) ? "orange" : "#BDBDBD" } })), /* @__PURE__ */ React.createElement(IconButton, { title: "error", disabled: !statusMessages.some((m) => m.type === EInstanceMessageType.SIGNAL && m.level === ESignalMessageLevel.ERROR), onClick: () => show(ESignalMessageLevel.ERROR), style: { marginLeft: "-16px" } }, /* @__PURE__ */ React.createElement(ErrorIcon, { style: { color: statusMessages.some((m) => m.type === EInstanceMessageType.SIGNAL && m.level === ESignalMessageLevel.ERROR) ? "red" : "#BDBDBD" } }))));
426
444
  };
427
445
  const statusClear = (level2) => {
428
446
  setStatusMessages(statusMessages.filter((m) => m.level !== level2));
429
447
  setShowStatusDialog(false);
430
448
  };
431
449
  const onError = (error2, _file) => {
432
- addMessage(SignalMessageLevelEnum.ERROR, error2.message);
450
+ addMessage(ESignalMessageLevel.ERROR, error2.message);
433
451
  };
434
452
  const onRename = (file, newName) => {
435
453
  let [namespace, pod, container] = file.path.split("/").slice(1);
@@ -452,10 +470,10 @@ const EntityKwirthFilemanContent = (props) => {
452
470
  if (accessKey && instance?.current && webSocket) {
453
471
  let [namespace, pod, container] = folder.split("/").slice(1);
454
472
  let filemanMessage = {
455
- flow: InstanceMessageFlowEnum.REQUEST,
456
- action: InstanceMessageActionEnum.COMMAND,
473
+ flow: EInstanceMessageFlow.REQUEST,
474
+ action: EInstanceMessageAction.COMMAND,
457
475
  channel: "fileman",
458
- type: InstanceMessageTypeEnum.DATA,
476
+ type: EInstanceMessageType.DATA,
459
477
  accessKey: accessKeySerialize(accessKey),
460
478
  instance: instance.current,
461
479
  id: v4(),
@@ -478,10 +496,10 @@ const EntityKwirthFilemanContent = (props) => {
478
496
  let accessKey = cluster2.accessKeys.get("fileman$read");
479
497
  if (accessKey && instance?.current && webSocket) {
480
498
  let filemanMessage = {
481
- flow: InstanceMessageFlowEnum.REQUEST,
482
- action: InstanceMessageActionEnum.COMMAND,
499
+ flow: EInstanceMessageFlow.REQUEST,
500
+ action: EInstanceMessageAction.COMMAND,
483
501
  channel: "fileman",
484
- type: InstanceMessageTypeEnum.DATA,
502
+ type: EInstanceMessageType.DATA,
485
503
  accessKey: accessKeySerialize(accessKey),
486
504
  instance: instance.current,
487
505
  id: v4(),
@@ -496,10 +514,10 @@ const EntityKwirthFilemanContent = (props) => {
496
514
  let payload = JSON.stringify(filemanMessage);
497
515
  webSocket.send(payload);
498
516
  } else {
499
- addMessage(SignalMessageLevelEnum.ERROR, "Have no instance/accessKey");
517
+ addMessage(ESignalMessageLevel.ERROR, "Have no instance/accessKey");
500
518
  }
501
519
  } else {
502
- addMessage(SignalMessageLevelEnum.ERROR, "Have no cluster");
520
+ addMessage(ESignalMessageLevel.ERROR, "Have no cluster");
503
521
  }
504
522
  };
505
523
  const onDelete = async (filesToDelete) => {
@@ -518,7 +536,7 @@ const EntityKwirthFilemanContent = (props) => {
518
536
  let accessKey = cluster2.accessKeys.get("fileman$read");
519
537
  if (accessKey) {
520
538
  for (let file of filesToDownload) {
521
- const url = `${cluster2.url}/channel/fileman/download?key=${instance.current}&filename=${file.path}`;
539
+ const url = `${cluster2.url}/${runningInstance}/channel/fileman/download?key=${instance.current}&filename=${file.path}`;
522
540
  try {
523
541
  const response = await fetch(url, { headers: { "Authorization": "Bearer " + accessKeySerialize(accessKey) } });
524
542
  if (response.ok) {
@@ -533,18 +551,18 @@ const EntityKwirthFilemanContent = (props) => {
533
551
  URL.revokeObjectURL(link.href);
534
552
  } else {
535
553
  console.error(`Error downloading file: ${file.path}`);
536
- addMessage(SignalMessageLevelEnum.ERROR, `Error downloading file ${file.path}: (${response.status}) ${await response.text()}`);
554
+ addMessage(ESignalMessageLevel.ERROR, `Error downloading file ${file.path}: (${response.status}) ${await response.text()}`);
537
555
  }
538
556
  } catch (error2) {
539
557
  console.error(`Error downloading file: ${file.path}`, error2);
540
- addMessage(SignalMessageLevelEnum.ERROR, `Error downloading file ${file.path}: ${error2}`);
558
+ addMessage(ESignalMessageLevel.ERROR, `Error downloading file ${file.path}: ${error2}`);
541
559
  }
542
560
  }
543
561
  } else {
544
- addMessage(SignalMessageLevelEnum.ERROR, "Have no instance/accessKey");
562
+ addMessage(ESignalMessageLevel.ERROR, "Have no instance/accessKey");
545
563
  }
546
564
  } else {
547
- addMessage(SignalMessageLevelEnum.ERROR, "Have no cluster");
565
+ addMessage(ESignalMessageLevel.ERROR, "Have no cluster");
548
566
  }
549
567
  };
550
568
  const onPaste = (filesToPaste, destFolder, operation) => {
@@ -570,7 +588,7 @@ const EntityKwirthFilemanContent = (props) => {
570
588
  style: { marginTop: -4, marginBottom: 4, flexShrink: 0 },
571
589
  action: actionButtons()
572
590
  }
573
- )), started && /* @__PURE__ */ React.createElement(Grid, { ref: filemanBoxRef, style: { height: `calc(100vh - ${filemanBoxTop}px - 35px)` } }, /* @__PURE__ */ React.createElement(
591
+ )), started && /* @__PURE__ */ React.createElement(Grid, { ref: filemanBoxRef, style: { height: `calc(100vh - ${filemanBoxTop}px - 35px)`, borderRadius: "12px", overflow: "hidden" } }, /* @__PURE__ */ React.createElement(
574
592
  FileManager,
575
593
  {
576
594
  className: styles.customFm,
@@ -593,7 +611,10 @@ const EntityKwirthFilemanContent = (props) => {
593
611
  onDownload,
594
612
  enableFilePreview: false,
595
613
  initialPath: "",
596
- permissions
614
+ permissions,
615
+ maxNavigationPaneLevel: 3,
616
+ minFileActionsLevel: 3,
617
+ showBreadcrumb: true
597
618
  }
598
619
  ))))), showStatusDialog && /* @__PURE__ */ React.createElement(StatusLog, { level: statusLevel, onClose: () => setShowStatusDialog(false), statusMessages, onClear: statusClear }));
599
620
  };
@@ -1 +1 @@
1
- {"version":3,"file":"EntityKwirthFilemanContent.esm.js","sources":["../../src/components/EntityKwirthFilemanContent.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, { useEffect, useRef, useState } from 'react'\r\nimport { v4 as uuid } from 'uuid'\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_BACKSTAGE_KUBERNETES_LABELID, ANNOTATION_BACKSTAGE_KUBERNETES_LABELSELECTOR, isKwirthAvailable, ClusterValidPods, IStatusLine, getPodList, getContainerList, IBackendInfo } from '@jfvilas/plugin-kwirth-common'\r\nimport { MissingAnnotationEmptyState, useEntity } from '@backstage/plugin-catalog-react'\r\n\r\n// kwirth\r\nimport { kwirthFilemanApiRef } from '../api'\r\nimport { accessKeySerialize, InstanceMessageActionEnum, InstanceConfigViewEnum, IInstanceMessage, InstanceMessageTypeEnum, SignalMessageLevelEnum, InstanceConfigObjectEnum, IInstanceConfig, InstanceMessageFlowEnum, SignalMessageEventEnum, ISignalMessage } from '@jfvilas/kwirth-common'\r\n\r\n// kwirth fileman components\r\nimport { KwirthNews, ComponentNotFound, StatusLog, ClusterList, ErrorType } from '@jfvilas/plugin-kwirth-frontend'\r\nimport { FileManager, IError, IFileData } from '@jfvilas/react-file-manager'\r\nimport { VERSION } from '../version'\r\n\r\n// Material-UI\r\nimport { Grid, Card, CardHeader, Box, IconButton, Typography } from '@material-ui/core'\r\n\r\n// styles\r\nimport '@jfvilas/react-file-manager/dist/style.css'\r\nimport styles from './custom-fm.module.css'\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 LogoIcon from '../assets/kwirthfileman-logo.svg'\r\nimport SvgIconNamespace from'./icons/ns.svg'\r\nimport SvgIconPod from'./icons/pod.svg'\r\nimport SvgIconContainer from'./icons/docker-mark-blue.svg'\r\n\r\nexport interface IEntityKwirthFilemanProps {\r\n hideVersion?: boolean\r\n excludeContainers?: string[]\r\n}\r\n\r\n\r\nconst NamespaceIcon = (props: {height?:number}) => { return <img src={SvgIconNamespace} alt='ns' height={`${props.height||16}px`}/> }\r\nconst PodIcon = (props: {height?:number}) => { return <img src={SvgIconPod} alt='pod' height={`${props.height||16}px`}/> }\r\nconst ContainerIcon = (props: {height?:number}) => { return <img src={SvgIconContainer} height={`${props.height||16}px`}/> }\r\n\r\nexport const EntityKwirthFilemanContent: React.FC<IEntityKwirthFilemanProps> = (props:IEntityKwirthFilemanProps) => { \r\n const { entity } = useEntity()\r\n const kwirthFilemanApi = useApi(kwirthFilemanApiRef)\r\n const alertApi = useApi(alertApiRef)\r\n const [validClusters, 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 [statusMessages, setStatusMessages] = useState<IStatusLine[]>([])\r\n const [webSocket, setWebSocket] = useState<WebSocket>()\r\n const [showStatusDialog, setShowStatusDialog] = useState(false)\r\n const [statusLevel, setStatusLevel] = useState<SignalMessageLevelEnum>(SignalMessageLevelEnum.INFO)\r\n const [ backendVersion, setBackendVersion ] = useState<string>('')\r\n const [ backendInfo, setBackendInfo ] = useState<IBackendInfo>()\r\n const instance = useRef<string>()\r\n const [ stateFiles, setStateFiles ] = useState<IFileData[]>([])\r\n const files = useRef<IFileData[]>([])\r\n const [ currentPath, setCurrentPath] = useState('')\r\n const { loading, error } = useAsync ( async () => {\r\n if (backendVersion==='') setBackendVersion(await kwirthFilemanApi.getVersion())\r\n if (!backendInfo) setBackendInfo(await kwirthFilemanApi.getInfo())\r\n let reqScopes = ['fileman$read']\r\n let data:ClusterValidPods[] = await kwirthFilemanApi.requestAccess(entity, 'fileman', reqScopes)\r\n setResources(data)\r\n })\r\n const filemanBoxRef = useRef<HTMLDivElement | null>(null)\r\n const [filemanBoxTop, setFilemanBoxTop] = useState(0)\r\n let permissions={\r\n create: true,\r\n delete: true,\r\n download: true,\r\n copy: true,\r\n move: true,\r\n rename: true,\r\n upload: true\r\n }\r\n\r\n let icons = new Map()\r\n icons.set('namespace', { open:<NamespaceIcon height={18}/>, closed:<NamespaceIcon height={18}/>, grid:<NamespaceIcon height={40}/>, list:<NamespaceIcon height={18}/>, default:<NamespaceIcon height={18}/> })\r\n icons.set('pod', { open:<PodIcon height={18}/>, closed:<PodIcon height={18}/>, grid:<PodIcon height={40}/>, list:<PodIcon height={18}/>, default:<PodIcon height={18}/> })\r\n icons.set('container', { open:<ContainerIcon/>, closed:<ContainerIcon/>, grid:<ContainerIcon height={34}/>, list:<ContainerIcon height={16}/>, default:<ContainerIcon height={16}/> })\r\n\r\n interface IFileUploadConfig { \r\n url: string\r\n method?: \"POST\" | \"PUT\"\r\n headers?: { [key: string]: string }\r\n }\r\n let fileUploadConfig:IFileUploadConfig= {\r\n url: ''\r\n }\r\n\r\n let cluster = validClusters.find(cluster => cluster.name===selectedClusterName)\r\n if (cluster) {\r\n let accessKey = cluster.accessKeys.get('fileman$read')\r\n if (accessKey) {\r\n fileUploadConfig = {\r\n url: `${cluster.url}/channel/fileman/upload?key=${instance.current}`,\r\n method:'POST',\r\n headers: {\r\n 'Authorization': 'Bearer '+ accessKeySerialize(accessKey)\r\n }\r\n }\r\n }\r\n }\r\n \r\n let level = currentPath.split('/').length - 1\r\n if (level<3) {\r\n permissions = {\r\n create: false,\r\n delete: false,\r\n download: false,\r\n copy: false,\r\n move: false,\r\n rename: false,\r\n upload: false\r\n }\r\n }\r\n\r\n useEffect(() => {\r\n if (filemanBoxRef.current) setFilemanBoxTop(filemanBoxRef.current.getBoundingClientRect().top)\r\n })\r\n\r\n const clickStart = () => {\r\n if (!paused.current) {\r\n setStarted(true)\r\n paused.current=false\r\n setStopped(false)\r\n startFilemanViewer()\r\n }\r\n else {\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 stopFilemanViewer()\r\n }\r\n\r\n const onSelectCluster = (clusterName:string|undefined) => {\r\n if (started) onClickStop()\r\n if (clusterName) {\r\n setSelectedClusterName(clusterName)\r\n setSelectedPodNames([])\r\n setSelectedContainerNames([])\r\n setStatusMessages([])\r\n let cluster = validClusters.find(cluster => cluster.name === clusterName)\r\n\r\n if (cluster && cluster.pods) {\r\n let validNamespaces = Array.from(new Set(cluster.pods.map(pod => pod.namespace)))\r\n if (validNamespaces.length === 1) {\r\n setSelectedNamespaces(validNamespaces)\r\n let podList = getPodList (cluster.pods, validNamespaces)\r\n setSelectedPodNames(podList.map(pod => pod.name))\r\n setSelectedContainerNames(getContainerList(cluster.pods, validNamespaces, podList.map(pod => pod.name), props.excludeContainers || []))\r\n }\r\n else {\r\n setSelectedNamespaces([])\r\n }\r\n }\r\n }\r\n }\r\n\r\n enum FilemanCommandEnum {\r\n HOME = 'home',\r\n DIR = 'dir',\r\n CREATE = 'create',\r\n RENAME = 'rename',\r\n DELETE = 'delete',\r\n MOVE = 'move',\r\n COPY = 'copy',\r\n UPLOAD = 'upload',\r\n DOWNLOAD = 'download'\r\n }\r\n\r\n interface IFilemanMessage extends IInstanceMessage {\r\n msgtype: 'filemanmessage'\r\n id: string\r\n accessKey: string\r\n instance: string\r\n namespace: string\r\n group: string\r\n pod: string\r\n container: string\r\n command: FilemanCommandEnum\r\n params?: string[]\r\n }\r\n\r\n interface IFilemanMessageResponse extends IInstanceMessage {\r\n msgtype: 'filemanmessageresponse'\r\n id: string\r\n command: FilemanCommandEnum\r\n namespace: string\r\n group: string\r\n pod: string\r\n container: string\r\n data?: any\r\n }\r\n\r\n const processFilemanMessage = (wsEvent:any) => {\r\n let msg:IFilemanMessage = JSON.parse(wsEvent.data)\r\n\r\n switch (msg.type) {\r\n case InstanceMessageTypeEnum.DATA: {\r\n let response = JSON.parse(wsEvent.data) as IFilemanMessageResponse\r\n switch(response.action) {\r\n case InstanceMessageActionEnum.COMMAND: {\r\n switch(response.command) {\r\n case FilemanCommandEnum.HOME:\r\n let data = response.data as string[]\r\n let nss = Array.from (new Set (data.map(n => n.split('/')[0])))\r\n nss.map(ns => {\r\n if (!files.current.some(f => f.path === '/'+ ns)) {\r\n files.current.push ({ name: ns, isDirectory: true, path: '/'+ ns, class:'namespace' }) \r\n }\r\n let podNames = Array.from (new Set (data.filter(a => a.split('/')[0]===ns).map(o => o.split('/')[1])))\r\n podNames.map(p => {\r\n if (!files.current.some(f => f.path === '/'+ns+'/'+p)) {\r\n files.current.push ({ name: p, isDirectory: true, path: '/'+ns+'/'+p, class:'pod' })\r\n }\r\n let containers = Array.from (new Set (data.filter(a => a.split('/')[0]===ns && a.split('/')[1]===p).map(o => o.split('/')[2])))\r\n containers = containers.filter(c => !props.excludeContainers?.includes(c))\r\n containers.map(c => {\r\n if (!files.current.some(f => f.path === '/'+ns+'/'+p+'/'+c)) {\r\n files.current.push ({ name: c, isDirectory: true, path: '/'+ns+'/'+p+'/'+c, class:'container' })\r\n }\r\n })\r\n })\r\n })\r\n setStateFiles([...files.current])\r\n break\r\n case FilemanCommandEnum.DIR:\r\n let content = JSON.parse(response.data)\r\n if (content.status==='Success') {\r\n for (let o of content.metadata.object) {\r\n let name = o.name.split('/')[o.name.split('/').length-1]\r\n let e = {\r\n name,\r\n isDirectory: (o.type===1),\r\n path: o.name,\r\n updatedAt: new Date(+o.time).toISOString(),\r\n size: +o.size,\r\n ...(o.type===0? {class:'file'}:{})\r\n }\r\n let i = files.current.findIndex(f => f.path === e.path)\r\n if (i>=0)\r\n files.current[i]=e\r\n else\r\n files.current.push(e)\r\n }\r\n setStateFiles([...files.current])\r\n }\r\n else {\r\n addMessage( SignalMessageLevelEnum.ERROR, content.text || content.message)\r\n }\r\n break\r\n case FilemanCommandEnum.RENAME: {\r\n let content = JSON.parse(response.data)\r\n if (content.status!=='Success') addMessage( SignalMessageLevelEnum.ERROR, content.text || content.message)\r\n }\r\n break\r\n case FilemanCommandEnum.DELETE: {\r\n let content = JSON.parse(response.data)\r\n if (content.status==='Success') {\r\n let fname = content.metadata.object\r\n files.current = files.current.filter(f => f.path !== fname)\r\n files.current = files.current.filter(f => !f.path.startsWith(fname+'/'))\r\n setStateFiles([...files.current])\r\n }\r\n else {\r\n addMessage( SignalMessageLevelEnum.ERROR, content.text || content.message)\r\n }\r\n break\r\n }\r\n case FilemanCommandEnum.MOVE:\r\n case FilemanCommandEnum.COPY:\r\n case FilemanCommandEnum.CREATE: {\r\n let content = JSON.parse(response.data)\r\n if (content.status==='Success') {\r\n //filemanData.files = filemanData.files.filter(f => f.path !== content.metadata.object)\r\n let f = { \r\n name: (content.metadata.object as string).split('/').slice(-1)[0],\r\n isDirectory: (content.metadata.type===1),\r\n path: content.metadata.object,\r\n updatedAt: new Date(+content.metadata.time).toISOString(), \r\n size: +content.metadata.size,\r\n ...(content.metadata.type.type===0? {class:'file'}:{})\r\n }\r\n files.current.push(f)\r\n setStateFiles([...files.current])\r\n }\r\n else {\r\n addMessage( SignalMessageLevelEnum.ERROR, content.text || content.message)\r\n }\r\n break\r\n }\r\n }\r\n }\r\n break\r\n }\r\n break\r\n }\r\n case InstanceMessageTypeEnum.SIGNAL:\r\n let signalMessage = JSON.parse(wsEvent.data) as ISignalMessage\r\n if (signalMessage.flow === InstanceMessageFlowEnum.RESPONSE) {\r\n if (signalMessage.action === InstanceMessageActionEnum.START) {\r\n if (signalMessage.text) addMessage(SignalMessageLevelEnum.INFO, signalMessage.text)\r\n instance.current = signalMessage.instance\r\n }\r\n else {\r\n addMessage( SignalMessageLevelEnum.ERROR, wsEvent.data)\r\n }\r\n }\r\n else if (signalMessage.flow === InstanceMessageFlowEnum.UNSOLICITED) {\r\n let cluster = validClusters.find(cluster => cluster.name===selectedClusterName)\r\n if (cluster) {\r\n let accessKey = cluster.accessKeys.get('fileman$read')\r\n if (accessKey && instance?.current) {\r\n if (signalMessage.event === SignalMessageEventEnum.ADD) {\r\n let filemanMessage:IFilemanMessage = {\r\n flow: InstanceMessageFlowEnum.REQUEST,\r\n action: InstanceMessageActionEnum.COMMAND,\r\n channel: 'fileman',\r\n type: InstanceMessageTypeEnum.DATA,\r\n accessKey: accessKeySerialize(accessKey),\r\n instance: instance.current,\r\n id: uuid(),\r\n command: FilemanCommandEnum.HOME,\r\n namespace: signalMessage.namespace!,\r\n group: '',\r\n pod: signalMessage.pod!,\r\n container: signalMessage.container!,\r\n params: [],\r\n msgtype: 'filemanmessage'\r\n }\r\n let payload = JSON.stringify( filemanMessage )\r\n wsEvent.target.send(payload)\r\n if (signalMessage.text) addMessage( SignalMessageLevelEnum.INFO, signalMessage.text)\r\n }\r\n }\r\n else {\r\n addMessage( SignalMessageLevelEnum.INFO, 'Have no instance/accessKey')\r\n }\r\n }\r\n else {\r\n addMessage( SignalMessageLevelEnum.INFO, 'Have no cluster')\r\n }\r\n }\r\n break\r\n\r\n default:\r\n console.log(`Invalid message type ${msg.type}`)\r\n break\r\n }\r\n }\r\n\r\n const addMessage = (level:SignalMessageLevelEnum, text:string) => {\r\n alertApi.post({ message: text, severity: level, display:'transient' }) \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:IInstanceMessage\r\n try {\r\n instanceMessage = JSON.parse(wsEvent.data) as IInstanceMessage\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 'fileman':\r\n processFilemanMessage(wsEvent)\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) => {\r\n setWebSocket(ws)\r\n let cluster=validClusters.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.pods.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('fileman$read')\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:IInstanceConfig = {\r\n channel: 'fileman',\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: 'fileman$read',\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 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 fileman streaming')\r\n return\r\n }\r\n }\r\n\r\n const startFilemanViewer = () => {\r\n let cluster=validClusters.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 try {\r\n let ws = new WebSocket(cluster.url)\r\n ws.onopen = () => websocketOnOpen(ws)\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 }\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 stopFilemanViewer = () => {\r\n webSocket?.close()\r\n }\r\n\r\n const actionButtons = () => {\r\n let hasKey=false\r\n let cluster=validClusters.find(cluster => cluster.name===selectedClusterName)\r\n if (cluster) {\r\n hasKey = Boolean(cluster.accessKeys.get('fileman$read'))\r\n }\r\n\r\n return <>\r\n <IconButton onClick={() => clickStart()} title=\"Play\" disabled={started || !paused || selectedPodNames.length === 0 || !hasKey}>\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 const prepareText = (txt:string|undefined) => {\r\n return txt? (txt.length>25? txt.substring(0,25)+\"...\":txt) : 'N/A'\r\n }\r\n\r\n return (\r\n <Grid container direction='row' >\r\n <Grid item>\r\n <Typography variant='h5'>{prepareText(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 onError = (error: IError, _file: IFileData) => {\r\n addMessage( SignalMessageLevelEnum.ERROR, error.message)\r\n }\r\n\r\n const onRename\t= (file: IFileData, newName: string) => {\r\n let [namespace,pod,container] = file.path.split('/').slice(1)\r\n //filemanData.files = filemanData.files.filter (f => f.path!==file.path)\r\n files.current = files.current.filter (f => f.path!==file.path)\r\n setStateFiles([...files.current])\r\n sendCommand(FilemanCommandEnum.RENAME, namespace, pod, container, [file.path, newName])\r\n }\r\n\r\n const onRefresh = () => {\r\n if (level >= 3) {\r\n files.current = files.current.filter ( f => !f.path.startsWith(currentPath+'/'))\r\n //files.current = files.current.filter ( f => f.path!==currentPath)\r\n getLocalDir(currentPath+'/')\r\n }\r\n else {\r\n sendCommand(FilemanCommandEnum.HOME, '', '', '', [])\r\n }\r\n\r\n }\r\n \r\n const getLocalDir = (folder:string) => {\r\n let cluster = validClusters.find(cluster => cluster.name===selectedClusterName)\r\n if (cluster) {\r\n let accessKey = cluster.accessKeys.get('fileman$read')\r\n if (accessKey && instance?.current && webSocket) {\r\n let [namespace,pod,container] = folder.split('/').slice(1)\r\n let filemanMessage:IFilemanMessage = {\r\n flow: InstanceMessageFlowEnum.REQUEST,\r\n action: InstanceMessageActionEnum.COMMAND,\r\n channel: 'fileman',\r\n type: InstanceMessageTypeEnum.DATA,\r\n accessKey: accessKeySerialize(accessKey),\r\n instance: instance.current,\r\n id: uuid(),\r\n command: FilemanCommandEnum.DIR,\r\n namespace: namespace,\r\n group: '',\r\n pod: pod,\r\n container: container,\r\n params: [folder],\r\n msgtype: 'filemanmessage'\r\n }\r\n let payload = JSON.stringify(filemanMessage)\r\n webSocket.send(payload)\r\n }\r\n }\r\n }\r\n\r\n const sendCommand = (command: FilemanCommandEnum, namespace:string, pod:string, container:string, params:string[]) => {\r\n let cluster = validClusters.find(cluster => cluster.name===selectedClusterName)\r\n if (cluster) {\r\n let accessKey = cluster.accessKeys.get('fileman$read')\r\n if (accessKey && instance?.current && webSocket) { \r\n let filemanMessage:IFilemanMessage = {\r\n flow: InstanceMessageFlowEnum.REQUEST,\r\n action: InstanceMessageActionEnum.COMMAND,\r\n channel: 'fileman',\r\n type: InstanceMessageTypeEnum.DATA,\r\n accessKey: accessKeySerialize(accessKey),\r\n instance: instance.current,\r\n id: uuid(),\r\n command: command,\r\n namespace: namespace,\r\n group: '',\r\n pod: pod,\r\n container: container,\r\n params: params,\r\n msgtype: 'filemanmessage'\r\n }\r\n let payload = JSON.stringify( filemanMessage )\r\n webSocket.send(payload)\r\n }\r\n else {\r\n addMessage( SignalMessageLevelEnum.ERROR, 'Have no instance/accessKey')\r\n }\r\n }\r\n else {\r\n addMessage( SignalMessageLevelEnum.ERROR, 'Have no cluster')\r\n }\r\n }\r\n\r\n const onDelete = async (filesToDelete: IFileData[]) => {\r\n for (let file of filesToDelete) {\r\n let [namespace,pod,container] = file.path.split('/').slice(1)\r\n sendCommand(FilemanCommandEnum.DELETE, namespace, pod, container, [file.path])\r\n }\r\n }\r\n\r\n const onCreateFolder = async (name: string, parentFolder: IFileData) => {\r\n let [namespace,pod,container] = parentFolder.path.split('/').slice(1)\r\n sendCommand(FilemanCommandEnum.CREATE, namespace, pod, container, [parentFolder.path + '/' + name])\r\n }\r\n\r\n const onDownload = async (filesToDownload: Array<IFileData>) => {\r\n let cluster = validClusters.find(cluster => cluster.name===selectedClusterName)\r\n if (cluster) {\r\n let accessKey = cluster.accessKeys.get('fileman$read')\r\n if (accessKey) {\r\n\r\n for (let file of filesToDownload) {\r\n const url = `${cluster.url}/channel/fileman/download?key=${instance.current}&filename=${file.path}`\r\n \r\n try {\r\n const response = await fetch(url, { headers: { 'Authorization': 'Bearer '+ accessKeySerialize(accessKey) } })\r\n\r\n if (response.ok) {\r\n const blob = await response.blob()\r\n\r\n const link = document.createElement('a')\r\n link.href = URL.createObjectURL(blob)\r\n link.download = file.path.split('/').slice(-1)[0]\r\n if (file.isDirectory) link.download += '.tar.gz'\r\n document.body.appendChild(link)\r\n link.click()\r\n document.body.removeChild(link)\r\n URL.revokeObjectURL(link.href)\r\n }\r\n else {\r\n console.error(`Error downloading file: ${file.path}`)\r\n addMessage( SignalMessageLevelEnum.ERROR, `Error downloading file ${file.path}: (${response.status}) ${await response.text()}`)\r\n }\r\n }\r\n catch (error) {\r\n console.error(`Error downloading file: ${file.path}`, error)\r\n addMessage( SignalMessageLevelEnum.ERROR, `Error downloading file ${file.path}: ${error}`)\r\n }\r\n }\r\n }\r\n else {\r\n addMessage( SignalMessageLevelEnum.ERROR, 'Have no instance/accessKey')\r\n }\r\n }\r\n else {\r\n addMessage( SignalMessageLevelEnum.ERROR, 'Have no cluster')\r\n }\r\n }\r\n\r\n const onPaste = (filesToPaste: Array<IFileData>, destFolder:IFileData, operation:string) => {\r\n let command = operation==='move'? FilemanCommandEnum.MOVE : FilemanCommandEnum.COPY\r\n for (let file of filesToPaste) {\r\n let [namespace,pod,container] = file.path.split('/').slice(1)\r\n sendCommand(command, namespace, pod, container, [file.path, destFolder.path])\r\n } \r\n }\r\n\r\n const onFolderChange = (folder:string) => {\r\n setCurrentPath(folder)\r\n folder +='/'\r\n let level = folder.split('/').length - 1\r\n if (level > 3) getLocalDir(folder)\r\n }\r\n\r\n const onFileUploading = (file: IFileData, _parentFolder: IFileData) => { \r\n return { filename: currentPath + '/' + file.name }\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-fileman' annotation={[ANNOTATION_BACKSTAGE_KUBERNETES_LABELID, ANNOTATION_BACKSTAGE_KUBERNETES_LABELSELECTOR]}/>\r\n )}\r\n\r\n { isKwirthAvailable(entity) && !loading && validClusters && validClusters.length===0 &&\r\n <ComponentNotFound error={ErrorType.NO_CLUSTERS} entity={entity}/>\r\n }\r\n\r\n { isKwirthAvailable(entity) && !loading && validClusters && validClusters.length>0 && validClusters.reduce((sum,cluster) => sum+cluster.pods.length, 0)===0 &&\r\n <ComponentNotFound error={ErrorType.NO_PODS} entity={entity}/>\r\n }\r\n\r\n { isKwirthAvailable(entity) && !loading && validClusters && validClusters.length>0 && validClusters.reduce((sum,cluster) => sum+cluster.pods.length, 0)>0 &&\r\n <Box sx={{ display: 'flex', height:'100%'}}>\r\n <Box sx={{ width: '200px', maxWidth:'200px'}}>\r\n <Grid container direction='column'>\r\n <Grid item> \r\n <Card>\r\n <ClusterList resources={validClusters} selectedClusterName={selectedClusterName} onSelect={onSelectCluster}/>\r\n </Card>\r\n </Grid>\r\n {!props.hideVersion &&\r\n <Grid item>\r\n <Card>\r\n <KwirthNews latestVersions={backendInfo} backendVersion={backendVersion} ownVersion={VERSION}/>\r\n </Card>\r\n </Grid>\r\n }\r\n </Grid>\r\n </Box>\r\n\r\n <Box sx={{ flexGrow: 1, flex:1, overflow:'hidden', p:1, marginLeft:'8px' }}>\r\n\r\n { !selectedClusterName && \r\n <img src={LogoIcon} style={{ left:'40%', marginTop:'10%', width:'20%', position:'relative' }} />\r\n }\r\n\r\n { selectedClusterName && <>\r\n <Card style={{ marginTop:-8, marginBottom:'8px' }}>\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 </Card>\r\n { started && <Grid ref={filemanBoxRef} style={{height: `calc(100vh - ${filemanBoxTop}px - 35px)`}}>\r\n <FileManager \r\n className={styles.customFm}\r\n files={stateFiles}\r\n filePreviewPath='http://avoid-console-error'\r\n primaryColor='#1976d2'\r\n fontFamily='\"Helvetica Neue\", Helvetica, Roboto, Arial, sans-serif'\r\n height='100%'\r\n actions={new Map()}\r\n icons={icons} \r\n fileUploadConfig={fileUploadConfig}\r\n onCreateFolder={onCreateFolder}\r\n onError={onError}\r\n onRename={onRename}\r\n onPaste={onPaste}\r\n onDelete={onDelete}\r\n onFolderChange={onFolderChange}\r\n onRefresh={onRefresh}\r\n onFileUploading={onFileUploading}\r\n onDownload={onDownload}\r\n enableFilePreview={false}\r\n initialPath={''}\r\n permissions={permissions}\r\n />\r\n </Grid>}\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","FilemanCommandEnum","content","uuid","level","p","error"],"mappings":"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"}
1
+ {"version":3,"file":"EntityKwirthFilemanContent.esm.js","sources":["../../src/components/EntityKwirthFilemanContent.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, { useEffect, useRef, useState } from 'react'\r\nimport { v4 as uuid } from 'uuid'\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_BACKSTAGE_KUBERNETES_LABELID, ANNOTATION_BACKSTAGE_KUBERNETES_LABELSELECTOR, isKwirthAvailable, ClusterValidPods, IStatusLine, getPodList, getContainerList, IBackendInfo } from '@jfvilas/plugin-kwirth-common'\r\nimport { MissingAnnotationEmptyState, useEntity } from '@backstage/plugin-catalog-react'\r\n\r\n// kwirth\r\nimport { kwirthFilemanApiRef } from '../api'\r\nimport { accessKeySerialize, IInstanceMessage, IInstanceConfig, ISignalMessage, EInstanceMessageType, EInstanceMessageAction, EInstanceMessageFlow, ESignalMessageEvent, EInstanceConfigObject, EInstanceConfigView, ESignalMessageLevel } from '@jfvilas/kwirth-common'\r\n\r\n// kwirth fileman components\r\nimport { KwirthNews, ComponentNotFound, StatusLog, ClusterList, ErrorType } from '@jfvilas/plugin-kwirth-frontend'\r\nimport { FileManager, IError } from '@jfvilas/react-file-manager'\r\nimport { VERSION } from '../version'\r\n\r\n// Material-UI\r\nimport { Grid, Card, CardHeader, Box, IconButton, Typography } from '@material-ui/core'\r\n\r\n// styles\r\nimport '@jfvilas/react-file-manager/dist/style.css'\r\nimport styles from './custom-fm.module.css'\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 LogoIcon from '../assets/kwirthfileman-logo.svg'\r\nimport SvgIconNamespace from'./icons/ns.svg'\r\nimport SvgIconPod from'./icons/pod.svg'\r\nimport SvgIconContainer from'./icons/docker-mark-blue.svg'\r\n\r\nexport interface IEntityKwirthFilemanProps {\r\n hideVersion?: boolean\r\n excludeContainers?: string[]\r\n}\r\n\r\n\r\nconst NamespaceIcon = (props: {height?:number}) => { return <img src={SvgIconNamespace} alt='ns' height={`${props.height||16}px`}/> }\r\nconst PodIcon = (props: {height?:number}) => { return <img src={SvgIconPod} alt='pod' height={`${props.height||16}px`}/> }\r\nconst ContainerIcon = (props: {height?:number}) => { return <img src={SvgIconContainer} height={`${props.height||16}px`}/> }\r\n\r\nexport const EntityKwirthFilemanContent: React.FC<IEntityKwirthFilemanProps> = (props:IEntityKwirthFilemanProps) => { \r\n const { entity } = useEntity()\r\n const kwirthFilemanApi = useApi(kwirthFilemanApiRef)\r\n const alertApi = useApi(alertApiRef)\r\n const [validClusters, 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 [statusMessages, setStatusMessages] = useState<IStatusLine[]>([])\r\n const [webSocket, setWebSocket] = useState<WebSocket>()\r\n const [showStatusDialog, setShowStatusDialog] = useState(false)\r\n const [statusLevel, setStatusLevel] = useState<ESignalMessageLevel>(ESignalMessageLevel.INFO)\r\n const [ backendVersion, setBackendVersion ] = useState<string>('')\r\n const [ backendInfo, setBackendInfo ] = useState<IBackendInfo>()\r\n const instance = useRef<string>()\r\n const [ stateFiles, setStateFiles ] = useState<IFileObject[]>([])\r\n const files = useRef<IFileObject[]>([])\r\n const [ currentPath, setCurrentPath] = useState('')\r\n const { loading, error } = useAsync ( async () => {\r\n if (backendVersion==='') setBackendVersion(await kwirthFilemanApi.getVersion())\r\n if (!backendInfo) setBackendInfo(await kwirthFilemanApi.getInfo())\r\n let reqScopes = ['fileman$read']\r\n let data:ClusterValidPods[] = await kwirthFilemanApi.requestAccess(entity, 'fileman', reqScopes)\r\n setResources(data)\r\n })\r\n const filemanBoxRef = useRef<HTMLDivElement | null>(null)\r\n const [filemanBoxTop, setFilemanBoxTop] = useState(0)\r\n const [ runningInstance, setRunningInstance] = useState<string|undefined>()\r\n let permissions={\r\n create: true,\r\n delete: true,\r\n download: true,\r\n copy: true,\r\n move: true,\r\n rename: true,\r\n upload: true\r\n }\r\n\r\n let icons = new Map()\r\n icons.set('namespace', { open:<NamespaceIcon height={18}/>, closed:<NamespaceIcon height={18}/>, grid:<NamespaceIcon height={40}/>, list:<NamespaceIcon height={18}/>, default:<NamespaceIcon height={18}/> })\r\n icons.set('pod', { open:<PodIcon height={18}/>, closed:<PodIcon height={18}/>, grid:<PodIcon height={40}/>, list:<PodIcon height={18}/>, default:<PodIcon height={18}/> })\r\n icons.set('container', { open:<ContainerIcon/>, closed:<ContainerIcon/>, grid:<ContainerIcon height={34}/>, list:<ContainerIcon height={16}/>, default:<ContainerIcon height={16}/> })\r\n\r\n interface IFileUploadConfig { \r\n url: string\r\n method?: \"POST\" | \"PUT\"\r\n headers?: { [key: string]: string }\r\n }\r\n let fileUploadConfig:IFileUploadConfig= {\r\n url: ''\r\n }\r\n\r\n let cluster = validClusters.find(cluster => cluster.name===selectedClusterName)\r\n if (cluster) {\r\n let accessKey = cluster.accessKeys.get('fileman$read')\r\n if (accessKey) {\r\n fileUploadConfig = {\r\n url: `${cluster.url}/${runningInstance}/channel/fileman/upload?key=${instance.current}`,\r\n method:'POST',\r\n headers: {\r\n 'Authorization': 'Bearer '+ accessKeySerialize(accessKey)\r\n }\r\n }\r\n }\r\n }\r\n \r\n let level = currentPath.split('/').length - 1\r\n if (level<3) {\r\n permissions = {\r\n create: false,\r\n delete: false,\r\n download: false,\r\n copy: false,\r\n move: false,\r\n rename: false,\r\n upload: false\r\n }\r\n }\r\n\r\n useEffect(() => {\r\n if (filemanBoxRef.current) setFilemanBoxTop(filemanBoxRef.current.getBoundingClientRect().top)\r\n })\r\n\r\n const clickStart = () => {\r\n if (!paused.current) {\r\n setStarted(true)\r\n paused.current=false\r\n setStopped(false)\r\n startFilemanViewer()\r\n }\r\n else {\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 stopFilemanViewer()\r\n }\r\n\r\n const onSelectCluster = (clusterName:string|undefined) => {\r\n if (started) onClickStop()\r\n if (clusterName) {\r\n setSelectedClusterName(clusterName)\r\n setSelectedPodNames([])\r\n setSelectedContainerNames([])\r\n setStatusMessages([])\r\n let cluster = validClusters.find(cluster => cluster.name === clusterName)\r\n\r\n if (cluster && cluster.pods) {\r\n let validNamespaces = Array.from(new Set(cluster.pods.map(pod => pod.namespace)))\r\n if (validNamespaces.length === 1) {\r\n setSelectedNamespaces(validNamespaces)\r\n let podList = getPodList (cluster.pods, validNamespaces)\r\n setSelectedPodNames(podList.map(pod => pod.name))\r\n setSelectedContainerNames(getContainerList(cluster.pods, validNamespaces, podList.map(pod => pod.name), props.excludeContainers || []))\r\n }\r\n else {\r\n setSelectedNamespaces([])\r\n }\r\n }\r\n }\r\n }\r\n\r\n interface IFileObject {\r\n name: string;\r\n displayName?: string;\r\n isDirectory: boolean;\r\n path: string;\r\n layout?: string;\r\n class?: string;\r\n children?: string|any;\r\n data?: any;\r\n categories?: string[];\r\n features?: string[];\r\n }\r\n\r\n enum FilemanCommandEnum {\r\n HOME = 'home',\r\n DIR = 'dir',\r\n CREATE = 'create',\r\n RENAME = 'rename',\r\n DELETE = 'delete',\r\n MOVE = 'move',\r\n COPY = 'copy',\r\n UPLOAD = 'upload',\r\n DOWNLOAD = 'download'\r\n }\r\n\r\n interface IFilemanMessage extends IInstanceMessage {\r\n msgtype: 'filemanmessage'\r\n id: string\r\n accessKey: string\r\n instance: string\r\n namespace: string\r\n group: string\r\n pod: string\r\n container: string\r\n command: FilemanCommandEnum\r\n params?: string[]\r\n }\r\n\r\n interface IFilemanMessageResponse extends IInstanceMessage {\r\n msgtype: 'filemanmessageresponse'\r\n id: string\r\n command: FilemanCommandEnum\r\n namespace: string\r\n group: string\r\n pod: string\r\n container: string\r\n data?: any\r\n }\r\n\r\n const processFilemanMessage = (wsEvent:any) => {\r\n let msg:IFilemanMessage = JSON.parse(wsEvent.data)\r\n\r\n switch (msg.type) {\r\n case EInstanceMessageType.DATA: {\r\n let response = JSON.parse(wsEvent.data) as IFilemanMessageResponse\r\n switch(response.action) {\r\n case EInstanceMessageAction.COMMAND: {\r\n switch(response.command) {\r\n case FilemanCommandEnum.HOME:\r\n let data = response.data as string[]\r\n let nss = Array.from (new Set (data.map(n => n.split('/')[0])))\r\n nss.forEach(ns => {\r\n if (!files.current.some(f => f.path === '/'+ ns)) {\r\n files.current.push ({ name: ns, isDirectory: true, path: '/'+ ns, class:'namespace' })\r\n }\r\n let podNames = Array.from (new Set (data.filter(a => a.split('/')[0]===ns).map(o => o.split('/')[1])))\r\n podNames.forEach(p => {\r\n if (!files.current.some(f => f.path === '/'+ns+'/'+p)) {\r\n files.current.push({ name: p, isDirectory: true, path: '/'+ns+'/'+p, class:'pod' })\r\n }\r\n let conts = Array.from (new Set (data.filter(a => a.split('/')[0]===ns && a.split('/')[1]===p).map(o => o.split('/')[2])))\r\n conts.forEach(c => {\r\n if (!files.current.some(f => f.path === '/'+ns+'/'+p+'/'+c)) {\r\n files.current.push ({ name: c, isDirectory: true, path: '/'+ns+'/'+p+'/'+c, class:'container' })\r\n }\r\n })\r\n })\r\n })\r\n // let data = response.data as string[]\r\n // let nss = Array.from (new Set (data.map(n => n.split('/')[0])))\r\n // nss.map(ns => {\r\n // if (!files.current.some(f => f.path === '/'+ ns)) {\r\n // files.current.push ({ name: ns, isDirectory: true, path: '/'+ ns, class:'namespace' }) \r\n // }\r\n // let podNames = Array.from (new Set (data.filter(a => a.split('/')[0]===ns).map(o => o.split('/')[1])))\r\n // podNames.map(p => {\r\n // if (!files.current.some(f => f.path === '/'+ns+'/'+p)) {\r\n // files.current.push ({ name: p, isDirectory: true, path: '/'+ns+'/'+p, class:'pod' })\r\n // }\r\n // let containers = Array.from (new Set (data.filter(a => a.split('/')[0]===ns && a.split('/')[1]===p).map(o => o.split('/')[2])))\r\n // containers = containers.filter(c => !props.excludeContainers?.includes(c))\r\n // containers.map(c => {\r\n // if (!files.current.some(f => f.path === '/'+ns+'/'+p+'/'+c)) {\r\n // files.current.push ({ name: c, isDirectory: true, path: '/'+ns+'/'+p+'/'+c, class:'container' })\r\n // }\r\n // })\r\n // })\r\n // })\r\n setStateFiles([...files.current])\r\n break\r\n case FilemanCommandEnum.DIR:\r\n let content = JSON.parse(response.data)\r\n if (content.status==='Success') {\r\n // for (let o of content.metadata.object) {\r\n // let name = o.name.split('/')[o.name.split('/').length-1]\r\n // let e = {\r\n // name,\r\n // isDirectory: (o.type===1),\r\n // path: o.name,\r\n // updatedAt: new Date(+o.time).toISOString(),\r\n // size: +o.size,\r\n // ...(o.type===0? {class:'file'}:{})\r\n // }\r\n // let i = files.current.findIndex(f => f.path === e.path)\r\n // if (i>=0)\r\n // files.current[i]=e\r\n // else\r\n // files.current.push(e)\r\n // }\r\n if (content.status!=='Success') {\r\n addMessage( ESignalMessageLevel.ERROR, content.text || content.message)\r\n }\r\n else {\r\n for (let o of content.metadata.object) {\r\n let name = o.name.split('/')[o.name.split('/').length-1]\r\n let e:IFileObject = { \r\n name,\r\n isDirectory: (o.type===1),\r\n path: o.name,\r\n data: {\r\n updatedAt: new Date(+o.time).toISOString(),\r\n size: +o.size,\r\n ...(o.type===0? {class:'file'}:{})\r\n }\r\n }\r\n files.current = files.current.filter(f => f.path !== e.path)\r\n files.current.push (e)\r\n }\r\n }\r\n setStateFiles([...files.current])\r\n }\r\n else {\r\n addMessage( ESignalMessageLevel.ERROR, content.text || content.message)\r\n }\r\n break\r\n case FilemanCommandEnum.RENAME: {\r\n let content = JSON.parse(response.data)\r\n if (content.status!=='Success') addMessage( ESignalMessageLevel.ERROR, content.text || content.message)\r\n }\r\n break\r\n case FilemanCommandEnum.DELETE: {\r\n let content = JSON.parse(response.data)\r\n if (content.status==='Success') {\r\n // let fname = content.metadata.object\r\n // files.current = files.current.filter(f => f.path !== fname)\r\n // files.current = files.current.filter(f => !f.path.startsWith(fname+'/'))\r\n let fname = content.metadata.object\r\n files.current = files.current.filter(f => f.path !== fname)\r\n files.current = files.current.filter(f => !f.path.startsWith(fname+'/'))\r\n setStateFiles([...files.current])\r\n }\r\n else {\r\n addMessage( ESignalMessageLevel.ERROR, content.text || content.message)\r\n }\r\n break\r\n }\r\n case FilemanCommandEnum.MOVE:\r\n case FilemanCommandEnum.COPY:\r\n case FilemanCommandEnum.CREATE: {\r\n let content = JSON.parse(response.data)\r\n if (content.status==='Success') {\r\n // let f = { \r\n // name: (content.metadata.object as string).split('/').slice(-1)[0],\r\n // isDirectory: (content.metadata.type===1),\r\n // path: content.metadata.object,\r\n // updatedAt: new Date(+content.metadata.time).toISOString(), \r\n // size: +content.metadata.size,\r\n // ...(content.metadata.type.type===0? {class:'file'}:{})\r\n // }\r\n // files.current.push(f)\r\n let e:IFileObject = { \r\n name: (content.metadata.object as string).split('/').slice(-1)[0],\r\n isDirectory: (content.metadata.type===1),\r\n path: content.metadata.object,\r\n data: {\r\n updatedAt: new Date(+content.metadata.time).toISOString(), \r\n size: +content.metadata.size,\r\n ...(content.metadata.type.type===0? {class:'file'}:{})\r\n }\r\n }\r\n files.current.push(e)\r\n setStateFiles([...files.current])\r\n }\r\n else {\r\n addMessage( ESignalMessageLevel.ERROR, content.text || content.message)\r\n }\r\n break\r\n }\r\n }\r\n }\r\n break\r\n }\r\n break\r\n }\r\n case EInstanceMessageType.SIGNAL:\r\n let signalMessage = JSON.parse(wsEvent.data) as ISignalMessage\r\n if (signalMessage.flow === EInstanceMessageFlow.RESPONSE) {\r\n switch(signalMessage.action) {\r\n case EInstanceMessageAction.START:\r\n if (signalMessage.text) addMessage(ESignalMessageLevel.INFO, signalMessage.text)\r\n instance.current = signalMessage.instance\r\n break\r\n case EInstanceMessageAction.RI:\r\n setRunningInstance(signalMessage.data)\r\n break\r\n case EInstanceMessageAction.COMMAND:\r\n if (signalMessage.text) addMessage(signalMessage.level, signalMessage.text)\r\n break\r\n default:\r\n addMessage( ESignalMessageLevel.ERROR, wsEvent.data)\r\n break\r\n }\r\n }\r\n else if (signalMessage.flow === EInstanceMessageFlow.UNSOLICITED) {\r\n let cluster = validClusters.find(cluster => cluster.name===selectedClusterName)\r\n if (cluster) {\r\n let accessKey = cluster.accessKeys.get('fileman$read')\r\n if (accessKey && instance?.current) {\r\n if (signalMessage.event === ESignalMessageEvent.ADD) {\r\n // request a RI id\r\n let instanceConfig:IInstanceMessage = {\r\n action: EInstanceMessageAction.RI,\r\n channel: 'fileman',\r\n flow: EInstanceMessageFlow.REQUEST,\r\n type: EInstanceMessageType.SIGNAL,\r\n instance: instance.current\r\n }\r\n wsEvent.target.send(JSON.stringify( instanceConfig ))\r\n\r\n // request HOME dir\r\n let filemanMessage:IFilemanMessage = {\r\n flow: EInstanceMessageFlow.REQUEST,\r\n action: EInstanceMessageAction.COMMAND,\r\n channel: 'fileman',\r\n type: EInstanceMessageType.DATA,\r\n accessKey: accessKeySerialize(accessKey),\r\n instance: instance.current,\r\n id: uuid(),\r\n command: FilemanCommandEnum.HOME,\r\n namespace: signalMessage.namespace!,\r\n group: '',\r\n pod: signalMessage.pod!,\r\n container: signalMessage.container!,\r\n params: [],\r\n msgtype: 'filemanmessage'\r\n }\r\n let payload = JSON.stringify( filemanMessage )\r\n wsEvent.target.send(payload)\r\n if (signalMessage.text) addMessage( ESignalMessageLevel.INFO, signalMessage.text)\r\n }\r\n }\r\n else {\r\n addMessage( ESignalMessageLevel.INFO, 'Have no instance/accessKey')\r\n }\r\n }\r\n else {\r\n addMessage( ESignalMessageLevel.INFO, 'Have no cluster')\r\n }\r\n }\r\n break\r\n\r\n default:\r\n console.log(`Invalid message type ${msg.type}`)\r\n break\r\n }\r\n }\r\n\r\n const addMessage = (level:ESignalMessageLevel, text:string) => {\r\n alertApi.post({ message: text, severity: level, display:'transient' }) \r\n setStatusMessages ((prev) => [...prev, {level, text, type: EInstanceMessageType.SIGNAL }])\r\n }\r\n\r\n const websocketOnMessage = (wsEvent:any) => {\r\n let instanceMessage:IInstanceMessage\r\n try {\r\n instanceMessage = JSON.parse(wsEvent.data) as IInstanceMessage\r\n }\r\n catch (err:any) {\r\n addMessage(ESignalMessageLevel.ERROR, 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 'fileman':\r\n processFilemanMessage(wsEvent)\r\n break\r\n default:\r\n addMessage (ESignalMessageLevel.ERROR, 'Invalid channel in message: '+instanceMessage.channel)\r\n addMessage (ESignalMessageLevel.ERROR, 'Invalid message: '+JSON.stringify(instanceMessage))\r\n break\r\n }\r\n }\r\n\r\n const websocketOnOpen = (ws:WebSocket) => {\r\n setWebSocket(ws)\r\n let cluster=validClusters.find(cluster => cluster.name === selectedClusterName)\r\n if (!cluster) {\r\n addMessage(ESignalMessageLevel.ERROR,'No cluster selected')\r\n return\r\n }\r\n let pods = cluster.pods.filter(p => selectedNamespaces.includes(p.namespace))\r\n if (!pods) {\r\n addMessage(ESignalMessageLevel.ERROR,'No pods found')\r\n return\r\n }\r\n let accessKey = cluster.accessKeys.get('fileman$read')\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:IInstanceConfig = {\r\n channel: 'fileman',\r\n objects: EInstanceConfigObject.PODS,\r\n action: EInstanceMessageAction.START,\r\n flow: EInstanceMessageFlow.REQUEST,\r\n instance: '',\r\n accessKey: accessKeySerialize(accessKey),\r\n scope: 'fileman$read',\r\n view: (selectedContainerNames.length > 0 ? EInstanceConfigView.CONTAINER : EInstanceConfigView.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 type: EInstanceMessageType.SIGNAL\r\n }\r\n ws.send(JSON.stringify(iConfig))\r\n }\r\n else {\r\n addMessage(ESignalMessageLevel.ERROR,'No accessKey for starting fileman streaming')\r\n return\r\n }\r\n }\r\n\r\n const startFilemanViewer = () => {\r\n let cluster=validClusters.find(cluster => cluster.name===selectedClusterName);\r\n if (!cluster) {\r\n addMessage(ESignalMessageLevel.ERROR,'No cluster selected')\r\n return\r\n }\r\n\r\n try {\r\n let ws = new WebSocket(cluster.url)\r\n ws.onopen = () => websocketOnOpen(ws)\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 }\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 stopFilemanViewer = () => {\r\n webSocket?.close()\r\n }\r\n\r\n const actionButtons = () => {\r\n let hasKey=false\r\n let cluster=validClusters.find(cluster => cluster.name===selectedClusterName)\r\n if (cluster) {\r\n hasKey = Boolean(cluster.accessKeys.get('fileman$read'))\r\n }\r\n\r\n return <>\r\n <IconButton onClick={() => clickStart()} title=\"Play\" disabled={started || !paused || selectedPodNames.length === 0 || !hasKey}>\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:ESignalMessageLevel) => {\r\n setShowStatusDialog(true)\r\n setStatusLevel(level)\r\n }\r\n\r\n const prepareText = (txt:string|undefined) => {\r\n return txt? (txt.length>25? txt.substring(0,25)+\"...\":txt) : 'N/A'\r\n }\r\n\r\n return (\r\n <Grid container direction='row' >\r\n <Grid item>\r\n <Typography variant='h5'>{prepareText(title)}</Typography>\r\n </Grid>\r\n <Grid item style={{marginTop:'-8px'}}>\r\n <IconButton title=\"info\" disabled={!statusMessages.some(m=>m.type === EInstanceMessageType.SIGNAL && m.level=== ESignalMessageLevel.INFO)} onClick={() => show(ESignalMessageLevel.INFO)}>\r\n <InfoIcon style={{ color:statusMessages.some(m=>m.type === EInstanceMessageType.SIGNAL && m.level=== ESignalMessageLevel.INFO)?'#1D63ED':'#BDBDBD'}}/>\r\n </IconButton>\r\n <IconButton title=\"warning\" disabled={!statusMessages.some(m=>m.type === EInstanceMessageType.SIGNAL && m.level=== ESignalMessageLevel.WARNING)} onClick={() => show(ESignalMessageLevel.WARNING)} style={{marginLeft:'-16px'}}>\r\n <WarningIcon style={{ color:statusMessages.some(m=>m.type === EInstanceMessageType.SIGNAL && m.level=== ESignalMessageLevel.WARNING)?'orange':'#BDBDBD'}}/>\r\n </IconButton>\r\n <IconButton title=\"error\" disabled={!statusMessages.some(m=>m.type === EInstanceMessageType.SIGNAL && m.level=== ESignalMessageLevel.ERROR)} onClick={() => show(ESignalMessageLevel.ERROR)} style={{marginLeft:'-16px'}}>\r\n <ErrorIcon style={{ color:statusMessages.some(m=>m.type === EInstanceMessageType.SIGNAL && m.level=== ESignalMessageLevel.ERROR)?'red':'#BDBDBD'}}/>\r\n </IconButton>\r\n </Grid>\r\n </Grid>\r\n )\r\n }\r\n\r\n const statusClear = (level: ESignalMessageLevel) => {\r\n setStatusMessages(statusMessages.filter(m=> m.level!==level))\r\n setShowStatusDialog(false)\r\n }\r\n\r\n const onError = (error: IError, _file: IFileObject) => {\r\n addMessage( ESignalMessageLevel.ERROR, error.message)\r\n }\r\n\r\n const onRename\t= (file: IFileObject, newName: string) => {\r\n let [namespace,pod,container] = file.path.split('/').slice(1)\r\n //filemanData.files = filemanData.files.filter (f => f.path!==file.path)\r\n files.current = files.current.filter (f => f.path!==file.path)\r\n setStateFiles([...files.current])\r\n sendCommand(FilemanCommandEnum.RENAME, namespace, pod, container, [file.path, newName])\r\n }\r\n\r\n const onRefresh = () => {\r\n if (level >= 3) {\r\n files.current = files.current.filter ( f => !f.path.startsWith(currentPath+'/'))\r\n getLocalDir(currentPath+'/')\r\n }\r\n else {\r\n sendCommand(FilemanCommandEnum.HOME, '', '', '', [])\r\n }\r\n\r\n }\r\n \r\n const getLocalDir = (folder:string) => {\r\n let cluster = validClusters.find(cluster => cluster.name===selectedClusterName)\r\n if (cluster) {\r\n let accessKey = cluster.accessKeys.get('fileman$read')\r\n if (accessKey && instance?.current && webSocket) {\r\n let [namespace,pod,container] = folder.split('/').slice(1)\r\n let filemanMessage:IFilemanMessage = {\r\n flow: EInstanceMessageFlow.REQUEST,\r\n action: EInstanceMessageAction.COMMAND,\r\n channel: 'fileman',\r\n type: EInstanceMessageType.DATA,\r\n accessKey: accessKeySerialize(accessKey),\r\n instance: instance.current,\r\n id: uuid(),\r\n command: FilemanCommandEnum.DIR,\r\n namespace: namespace,\r\n group: '',\r\n pod: pod,\r\n container: container,\r\n params: [folder],\r\n msgtype: 'filemanmessage'\r\n }\r\n let payload = JSON.stringify(filemanMessage)\r\n webSocket.send(payload)\r\n }\r\n }\r\n }\r\n\r\n const sendCommand = (command: FilemanCommandEnum, namespace:string, pod:string, container:string, params:string[]) => {\r\n let cluster = validClusters.find(cluster => cluster.name===selectedClusterName)\r\n if (cluster) {\r\n let accessKey = cluster.accessKeys.get('fileman$read')\r\n if (accessKey && instance?.current && webSocket) { \r\n let filemanMessage:IFilemanMessage = {\r\n flow: EInstanceMessageFlow.REQUEST,\r\n action: EInstanceMessageAction.COMMAND,\r\n channel: 'fileman',\r\n type: EInstanceMessageType.DATA,\r\n accessKey: accessKeySerialize(accessKey),\r\n instance: instance.current,\r\n id: uuid(),\r\n command: command,\r\n namespace: namespace,\r\n group: '',\r\n pod: pod,\r\n container: container,\r\n params: params,\r\n msgtype: 'filemanmessage'\r\n }\r\n let payload = JSON.stringify( filemanMessage )\r\n webSocket.send(payload)\r\n }\r\n else {\r\n addMessage( ESignalMessageLevel.ERROR, 'Have no instance/accessKey')\r\n }\r\n }\r\n else {\r\n addMessage( ESignalMessageLevel.ERROR, 'Have no cluster')\r\n }\r\n }\r\n\r\n const onDelete = async (filesToDelete: IFileObject[]) => {\r\n for (let file of filesToDelete) {\r\n let [namespace,pod,container] = file.path.split('/').slice(1)\r\n sendCommand(FilemanCommandEnum.DELETE, namespace, pod, container, [file.path])\r\n }\r\n }\r\n\r\n const onCreateFolder = async (name: string, parentFolder: IFileObject) => {\r\n let [namespace,pod,container] = parentFolder.path.split('/').slice(1)\r\n sendCommand(FilemanCommandEnum.CREATE, namespace, pod, container, [parentFolder.path + '/' + name])\r\n }\r\n\r\n const onDownload = async (filesToDownload: Array<IFileObject>) => {\r\n let cluster = validClusters.find(cluster => cluster.name===selectedClusterName)\r\n if (cluster) {\r\n let accessKey = cluster.accessKeys.get('fileman$read')\r\n if (accessKey) {\r\n\r\n for (let file of filesToDownload) {\r\n const url = `${cluster.url}/${runningInstance}/channel/fileman/download?key=${instance.current}&filename=${file.path}`\r\n \r\n try {\r\n const response = await fetch(url, { headers: { 'Authorization': 'Bearer '+ accessKeySerialize(accessKey) } })\r\n\r\n if (response.ok) {\r\n const blob = await response.blob()\r\n\r\n const link = document.createElement('a')\r\n link.href = URL.createObjectURL(blob)\r\n link.download = file.path.split('/').slice(-1)[0]\r\n if (file.isDirectory) link.download += '.tar.gz'\r\n document.body.appendChild(link)\r\n link.click()\r\n document.body.removeChild(link)\r\n URL.revokeObjectURL(link.href)\r\n }\r\n else {\r\n console.error(`Error downloading file: ${file.path}`)\r\n addMessage( ESignalMessageLevel.ERROR, `Error downloading file ${file.path}: (${response.status}) ${await response.text()}`)\r\n }\r\n }\r\n catch (error) {\r\n console.error(`Error downloading file: ${file.path}`, error)\r\n addMessage( ESignalMessageLevel.ERROR, `Error downloading file ${file.path}: ${error}`)\r\n }\r\n }\r\n }\r\n else {\r\n addMessage( ESignalMessageLevel.ERROR, 'Have no instance/accessKey')\r\n }\r\n }\r\n else {\r\n addMessage( ESignalMessageLevel.ERROR, 'Have no cluster')\r\n }\r\n }\r\n\r\n const onPaste = (filesToPaste: Array<IFileObject>, destFolder:IFileObject, operation:string) => {\r\n let command = operation==='move'? FilemanCommandEnum.MOVE : FilemanCommandEnum.COPY\r\n for (let file of filesToPaste) {\r\n let [namespace,pod,container] = file.path.split('/').slice(1)\r\n sendCommand(command, namespace, pod, container, [file.path, destFolder.path])\r\n } \r\n }\r\n\r\n const onFolderChange = (folder:string) => {\r\n setCurrentPath(folder)\r\n folder +='/'\r\n let level = folder.split('/').length - 1\r\n if (level > 3) getLocalDir(folder)\r\n }\r\n\r\n const onFileUploading = (file: IFileObject, _parentFolder: IFileObject) => { \r\n return { filename: currentPath + '/' + file.name }\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-fileman' annotation={[ANNOTATION_BACKSTAGE_KUBERNETES_LABELID, ANNOTATION_BACKSTAGE_KUBERNETES_LABELSELECTOR]}/>\r\n )}\r\n\r\n { isKwirthAvailable(entity) && !loading && validClusters && validClusters.length===0 &&\r\n <ComponentNotFound error={ErrorType.NO_CLUSTERS} entity={entity}/>\r\n }\r\n\r\n { isKwirthAvailable(entity) && !loading && validClusters && validClusters.length>0 && validClusters.reduce((sum,cluster) => sum+cluster.pods.length, 0)===0 &&\r\n <ComponentNotFound error={ErrorType.NO_PODS} entity={entity}/>\r\n }\r\n\r\n { isKwirthAvailable(entity) && !loading && validClusters && validClusters.length>0 && validClusters.reduce((sum,cluster) => sum+cluster.pods.length, 0)>0 &&\r\n <Box sx={{ display: 'flex', height:'100%'}}>\r\n <Box sx={{ width: '200px', maxWidth:'200px'}}>\r\n <Grid container direction='column'>\r\n <Grid item> \r\n <Card>\r\n <ClusterList resources={validClusters} selectedClusterName={selectedClusterName} onSelect={onSelectCluster}/>\r\n </Card>\r\n </Grid>\r\n {!props.hideVersion &&\r\n <Grid item>\r\n <Card>\r\n <KwirthNews latestVersions={backendInfo} backendVersion={backendVersion} ownVersion={VERSION}/>\r\n </Card>\r\n </Grid>\r\n }\r\n </Grid>\r\n </Box>\r\n\r\n <Box sx={{ flexGrow: 1, flex:1, overflow:'hidden', p:1, marginLeft:'8px' }}>\r\n\r\n { !selectedClusterName && \r\n <img src={LogoIcon} style={{ left:'40%', marginTop:'10%', width:'20%', position:'relative' }} />\r\n }\r\n\r\n { selectedClusterName && <>\r\n <Card style={{ marginTop:-8, marginBottom:'8px' }}>\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 </Card>\r\n { started && <Grid ref={filemanBoxRef} style={{height: `calc(100vh - ${filemanBoxTop}px - 35px)`, borderRadius:'12px', overflow:'hidden'}}>\r\n \r\n <FileManager \r\n className={styles.customFm}\r\n files={stateFiles}\r\n filePreviewPath='http://avoid-console-error'\r\n primaryColor='#1976d2'\r\n fontFamily='\"Helvetica Neue\", Helvetica, Roboto, Arial, sans-serif'\r\n height='100%'\r\n actions={new Map()}\r\n icons={icons} \r\n fileUploadConfig={fileUploadConfig}\r\n onCreateFolder={onCreateFolder}\r\n onError={onError}\r\n onRename={onRename}\r\n onPaste={onPaste}\r\n onDelete={onDelete}\r\n onFolderChange={onFolderChange}\r\n onRefresh={onRefresh}\r\n onFileUploading={onFileUploading}\r\n onDownload={onDownload}\r\n enableFilePreview={false}\r\n initialPath={''}\r\n permissions={permissions}\r\n maxNavigationPaneLevel={3}\r\n minFileActionsLevel={3}\r\n showBreadcrumb={true}\r\n />\r\n </Grid>}\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","FilemanCommandEnum","content","uuid","level","p","error"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import styleInject from '../node_modules_dist/style-inject/dist/style-inject.es.esm.js';
2
2
 
3
- var css_248z = ".file-explorer {\r\n box-shadow: 0px 2px 1px -1px rgba(0,0,0,0.2),0px 1px 1px 0px rgba(0,0,0,0.14),0px 1px 3px 0px rgba(0,0,0,0.12);\r\n border-radius: 4px;\r\n min-height: 150px;\r\n border: 0\r\n}\r\n\r\n.file-explorer .toolbar {\r\n border-top-right-radius: 4px;\r\n border-top-left-radius: 4px;\r\n min-height: 46px;\r\n background-color: #fcfcfc;\r\n}\r\n\r\n.file-explorer .breadcrumb {\r\n padding-top: 10px;\r\n min-height: 36px;\r\n}\r\n\r\n.file-explorer .statusbar {\r\n height: 20px;\r\n}\r\n\r\n.file-explorer .file-item {\r\n padding-top: 4px;\r\n font-size: 14px;\r\n}\r\n\r\n.file-explorer .sb-folder-name {\r\n font-size: 14px;\r\n}\r\n\r\n.file-explorer .folder-name {\r\n font-size: 14px;\r\n}\r\n\r\n.file-explorer .sb-folders-list::-webkit-scrollbar {\r\n width: 10px;\r\n height: 10px;\r\n}\r\n\r\n.file-explorer .files::-webkit-scrollbar {\r\n width: 10px;\r\n height: 10px;\r\n}\r\n\r\n.file-explorer .files {\r\n padding: 2px;\r\n column-gap: 2px;\r\n row-gap: 2px;\r\n}\r\n\r\n.file-explorer .files .file-item .selection-checkbox {\r\n top: 6px;\r\n}\r\n\r\n.file-explorer .files .file-item-container {\r\n margin: 0 0;\r\n}";
3
+ var css_248z = ".file-explorer *::-webkit-scrollbar {\r\n width: 12px !important;\r\n height: 12px !important;\r\n display: block !important;\r\n}\r\n\r\n.file-explorer *::-webkit-scrollbar-thumb {\r\n border-radius: 10px !important;\r\n}\r\n\r\n\r\n/* --- ESTILOS MODO CLARO (POR DEFECTO) --- */\r\n.file-explorer {\r\n box-shadow: 0px 2px 4px rgba(0,0,0,0.1);\r\n background-color: #ffffff;\r\n border-radius: 4px;\r\n min-height: 150px;\r\n border: 1px solid #e0e0e0;\r\n color: #000000;\r\n}\r\n\r\n.file-explorer *::-webkit-scrollbar-track {\r\n background: #f0f0f0 !important;\r\n}\r\n\r\n.file-explorer *::-webkit-scrollbar-thumb {\r\n background: #cdcdcd !important;\r\n border: 2px solid #f0f0f0 !important;\r\n}\r\n\r\n.file-explorer *::-webkit-scrollbar-thumb:hover {\r\n background: #a6a6a6 !important;\r\n}\r\n\r\n.file-explorer .toolbar {\r\n border-top-right-radius: 4px;\r\n border-top-left-radius: 4px;\r\n min-height: 46px;\r\n background-color: #f5f5f5;\r\n border-bottom: 1px solid #e0e0e0;\r\n}\r\n\r\n.file-explorer .breadcrumb {\r\n padding-top: 10px;\r\n min-height: 36px;\r\n color: #666666;\r\n}\r\n\r\n.file-explorer .file-item,\r\n.file-explorer .sb-folder-name,\r\n.file-explorer .folder-name {\r\n font-size: 14px;\r\n color: #000000;\r\n padding: 2px;\r\n}\r\n\r\n.file-explorer .sb-folder-name,\r\n.file-explorer .folder-name {\r\n font-size: 14px;\r\n color: #000000;\r\n}\r\n\r\n.file-explorer .files .file-item-container:hover {\r\n background-color: rgba(0, 0, 0, 0.04);\r\n}\r\n\r\n/* --- ESTILOS MODO OSCURO (ACTIVADOS POR DATA-THEME-MODE) --- */\r\n\r\n[data-theme-mode='dark'] .file-explorer {\r\n background-color: #424242 !important;\r\n border-color: #333333 !important;\r\n border-radius: 4px;\r\n overflow: hidden;\r\n color: #e0e0e0 !important;\r\n}\r\n\r\n[data-theme-mode='dark'] .file-explorer .toolbar,\r\n[data-theme-mode='dark'] .file-explorer .grid,\r\n[data-theme-mode='dark'] .file-explorer .list,\r\n[data-theme-mode='dark'] .file-explorer .bread-crumb-container,\r\n[data-theme-mode='dark'] .file-explorer .search-input,\r\n[data-theme-mode='dark'] .file-explorer .statusbar,\r\n[data-theme-mode='dark'] .file-explorer .sidebar-resize,\r\n[data-theme-mode='dark'] .file-explorer .navigation-pane,\r\n[data-theme-mode='dark'] .file-explorer .fm-context-menu,\r\n[data-theme-mode='dark'] .file-explorer .fm-modal-header,\r\n[data-theme-mode='dark'] .file-explorer .fm-modal-heading,\r\n[data-theme-mode='dark'] .file-explorer .file-delete-confirm,\r\n[data-theme-mode='dark'] .file-explorer .file-rename-folder-action,\r\n[data-theme-mode='dark'] .file-explorer .fm-rename-folder-input,\r\n[data-theme-mode='dark'] .file-explorer .fm-rename-folder-container,\r\n[data-theme-mode='dark'] .file-explorer .file-delete-confirm-text,\r\n[data-theme-mode='dark'] .file-explorer .fm-modal,\r\n[data-theme-mode='dark'] .file-explorer .divider,\r\n[data-theme-mode='dark'] .file-explorer .files-header,\r\n[data-theme-mode='dark'] .file-explorer .toggle-view {\r\n background-color: #424242 !important;\r\n color: #e0e0e0 !important;\r\n border-color: rgba(255, 255, 255, 0.12) !important;\r\n}\r\n\r\n[data-theme-mode='dark'] .fm-context-menu .file-context-menu-list ul li,\r\n[data-theme-mode='dark'] .toggle-view ul li {\r\n color: #e0e0e0 !important;\r\n}\r\n\r\n[data-theme-mode='dark'] .fm-context-menu .file-context-menu-list ul li:hover,\r\n[data-theme-mode='dark'] .toggle-view ul li:hover {\r\n background-color: rgba(255, 255, 255, 0.1) !important;\r\n color: #ffffff !important;\r\n}\r\n\r\n[data-theme-mode='dark'] .file-explorer .file-item,\r\n[data-theme-mode='dark'] .file-explorer .sb-folder-name,\r\n[data-theme-mode='dark'] .file-explorer .folder-name,\r\n[data-theme-mode='dark'] .item-action {\r\n color: #ffffff !important;\r\n}\r\n\r\n[data-theme-mode='dark'] .file-explorer .column-header {\r\n width: calc(70% - 45px) !important;\r\n}\r\n\r\n[data-theme-mode='dark'] .file-explorer .files .file-item-container:hover {\r\n background-color: rgba(255, 255, 255, 0.08) !important;\r\n}\r\n\r\n[data-theme-mode='dark'] .file-explorer *::-webkit-scrollbar-track {\r\n background: #424242 !important; /* Fondo oscuro del explorador */\r\n}\r\n\r\n[data-theme-mode='dark'] .file-explorer *::-webkit-scrollbar-thumb {\r\n background: #555555 !important; /* Gris que resalte en oscuro */\r\n border: 2px solid #424242 !important;\r\n}\r\n\r\n[data-theme-mode='dark'] .file-explorer *::-webkit-scrollbar-thumb:hover {\r\n background: #777777 !important;\r\n}";
4
4
  var styles = {};
5
5
  styleInject(css_248z);
6
6
 
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import * as _backstage_core_plugin_api from '@backstage/core-plugin-api';
2
2
  import { DiscoveryApi, FetchApi } from '@backstage/core-plugin-api';
3
+ import * as _backstage_frontend_plugin_api from '@backstage/frontend-plugin-api';
3
4
  import { Entity } from '@backstage/catalog-model';
4
5
  import { ClusterValidPods, IBackendInfo } from '@jfvilas/plugin-kwirth-common';
5
6
 
@@ -19,7 +20,7 @@ interface KwirthFilemanApi {
19
20
  getVersion(): Promise<any>;
20
21
  getInfo(): any;
21
22
  }
22
- declare const kwirthFilemanApiRef: _backstage_core_plugin_api.ApiRef<KwirthFilemanApi>;
23
+ declare const kwirthFilemanApiRef: _backstage_frontend_plugin_api.ApiRef<KwirthFilemanApi>;
23
24
 
24
25
  interface KwirthFilemanClientOptions {
25
26
  discoveryApi: DiscoveryApi;
@@ -1,4 +1,4 @@
1
- const VERSION = "0.13.10";
1
+ const VERSION = "0.14.2";
2
2
 
3
3
  export { VERSION };
4
4
  //# sourceMappingURL=version.esm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"version.esm.js","sources":["../src/version.ts"],"sourcesContent":["export const VERSION:string=\"0.13.10\"; \r\n"],"names":[],"mappings":"AAAO,MAAM,OAAA,GAAe;;;;"}
1
+ {"version":3,"file":"version.esm.js","sources":["../src/version.ts"],"sourcesContent":["export const VERSION:string=\"0.14.2\"; \r\n"],"names":[],"mappings":"AAAO,MAAM,OAAA,GAAe;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jfvilas/plugin-kwirth-fileman",
3
- "version": "0.13.10",
3
+ "version": "0.14.2",
4
4
  "description": "Frontend plugin for doing visual file management on Kubernetes containers",
5
5
  "keywords": [
6
6
  "Backstage",
@@ -64,21 +64,21 @@
64
64
  "test": "backstage-cli package test"
65
65
  },
66
66
  "dependencies": {
67
- "@backstage/catalog-model": "^1.7.6",
68
- "@backstage/core-components": "^0.18.3",
69
- "@backstage/core-plugin-api": "^1.12.0",
70
- "@backstage/frontend-plugin-api": "^0.13.1",
71
- "@backstage/integration-react": "^1.2.12",
72
- "@backstage/plugin-auth-react": "^0.1.21",
73
- "@backstage/plugin-catalog-react": "^1.21.3",
74
- "@jfvilas/react-file-manager": "^1.1.7",
67
+ "@backstage/catalog-model": "^1.7.7",
68
+ "@backstage/core-components": "^0.18.8",
69
+ "@backstage/core-plugin-api": "^1.12.4",
70
+ "@backstage/frontend-plugin-api": "^0.15.1",
71
+ "@backstage/integration-react": "^1.2.16",
72
+ "@backstage/plugin-auth-react": "^0.1.25",
73
+ "@backstage/plugin-catalog-react": "^2.1.0",
74
+ "@jfvilas/react-file-manager": "^1.4.23",
75
75
  "@material-ui/core": "^4.12.2",
76
76
  "@material-ui/icons": "^4.9.1",
77
77
  "@types/react": "^16.13.1 || ^17.0.0 || ^18.0.0",
78
78
  "react-use": "^17.2.4"
79
79
  },
80
80
  "devDependencies": {
81
- "@backstage/cli": "^0.34.5",
81
+ "@backstage/cli": "^0.36.0",
82
82
  "@testing-library/dom": "^10.0.0",
83
83
  "@testing-library/jest-dom": "^6.0.0",
84
84
  "@testing-library/react": "^15.0.0",