@prorobotech/openapi-k8s-toolkit 1.4.0-alpha.12 → 1.4.0-alpha.14

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.
Files changed (32) hide show
  1. package/dist/{index-DlJkWTNK.mjs → index-DcEC4xll.mjs} +2 -2
  2. package/dist/{index-DlJkWTNK.mjs.map → index-DcEC4xll.mjs.map} +1 -1
  3. package/dist/{index-CWMOa8gQ.mjs → index-DuYZpKMC.mjs} +698 -165
  4. package/dist/index-DuYZpKMC.mjs.map +1 -0
  5. package/dist/openapi-k8s-toolkit.es.js +1 -1
  6. package/dist/openapi-k8s-toolkit.umd.js +694 -160
  7. package/dist/openapi-k8s-toolkit.umd.js.map +1 -1
  8. package/dist/types/components/molecules/EnrichedTable/index.d.ts +2 -2
  9. package/dist/types/components/molecules/EnrichedTable/organisms/ClusterListTable/ClusterListTable.d.ts +24 -0
  10. package/dist/types/components/molecules/EnrichedTable/organisms/ClusterListTable/index.d.ts +2 -0
  11. package/dist/types/components/molecules/EnrichedTable/organisms/index.d.ts +2 -0
  12. package/dist/types/components/molecules/index.d.ts +2 -2
  13. package/dist/types/components/organisms/DynamicComponents/molecules/ActionsDropdown/hooks/useActionsDropdownHandlers/actionHandlers.d.ts +23 -0
  14. package/dist/types/components/organisms/DynamicComponents/molecules/ActionsDropdown/hooks/useActionsDropdownHandlers/handlers/index.d.ts +6 -0
  15. package/dist/types/components/organisms/DynamicComponents/molecules/ActionsDropdown/hooks/useActionsDropdownHandlers/handlers/useCreateFromFilesHandlers.d.ts +11 -0
  16. package/dist/types/components/organisms/DynamicComponents/molecules/ActionsDropdown/hooks/useActionsDropdownHandlers/handlers/useDrainHandlers.d.ts +12 -0
  17. package/dist/types/components/organisms/DynamicComponents/molecules/ActionsDropdown/hooks/useActionsDropdownHandlers/handlers/useEvictHandlers.d.ts +9 -0
  18. package/dist/types/components/organisms/DynamicComponents/molecules/ActionsDropdown/hooks/useActionsDropdownHandlers/handlers/useRerunHandlers.d.ts +11 -0
  19. package/dist/types/components/organisms/DynamicComponents/molecules/ActionsDropdown/hooks/useActionsDropdownHandlers/handlers/useRollbackHandlers.d.ts +11 -0
  20. package/dist/types/components/organisms/DynamicComponents/molecules/ActionsDropdown/hooks/useActionsDropdownHandlers/handlers/useScaleHandlers.d.ts +11 -0
  21. package/dist/types/components/organisms/DynamicComponents/molecules/ActionsDropdown/hooks/useActionsDropdownHandlers/helpers.d.ts +24 -0
  22. package/dist/types/components/organisms/DynamicComponents/molecules/ActionsDropdown/hooks/useActionsDropdownHandlers/index.d.ts +3 -0
  23. package/dist/types/components/organisms/DynamicComponents/molecules/ActionsDropdown/hooks/useActionsDropdownHandlers/types.d.ts +65 -0
  24. package/dist/types/components/organisms/DynamicComponents/molecules/ActionsDropdown/hooks/useActionsDropdownHandlers/useActionsDropdownHandlers.d.ts +38 -0
  25. package/dist/types/components/organisms/DynamicComponents/molecules/ActionsDropdown/modals/CreateFromFilesModal.d.ts +12 -0
  26. package/dist/types/components/organisms/DynamicComponents/molecules/ActionsDropdown/modals/CreateFromFilesModal.test.d.ts +1 -0
  27. package/dist/types/components/organisms/DynamicComponents/molecules/ActionsDropdown/modals/DownloadAsFilesModal.d.ts +11 -0
  28. package/dist/types/components/organisms/DynamicComponents/molecules/ActionsDropdown/modals/DownloadAsFilesModal.test.d.ts +1 -0
  29. package/dist/types/components/organisms/DynamicComponents/types/ActionsDropdown.d.ts +18 -0
  30. package/package.json +1 -1
  31. package/dist/index-CWMOa8gQ.mjs.map +0 -1
  32. package/dist/types/components/organisms/DynamicComponents/molecules/ActionsDropdown/hooks/useActionsDropdownHandlers.d.ts +0 -103
@@ -1,9 +1,9 @@
1
1
  import styled, { css, createGlobalStyle } from 'styled-components';
2
2
  import * as React$1 from 'react';
3
3
  import React__default, { useState, useRef, useLayoutEffect, useReducer, useEffect, useCallback, useMemo, Fragment, createContext, useContext, memo, createElement, isValidElement, cloneElement, useInsertionEffect, useSyncExternalStore, forwardRef, useImperativeHandle, PureComponent, Children, Component, lazy, Suspense } from 'react';
4
- import { Input, Tree, Modal, Alert, theme, Select, Tag, Flex, Typography, Breadcrumb, Spin, Menu, Tooltip as Tooltip$1, Space, Button, ConfigProvider, Popover, Card as Card$2, Row, Col, Tabs, notification, Form, Switch, Segmented, Table, Progress, Statistic, message, InputNumber, Dropdown, Slider, Result, DatePicker, Radio, Checkbox, Empty } from 'antd';
4
+ import { Input, Tree, Modal, Alert, theme, Select, Tag, Flex, Typography, Breadcrumb, Spin, Menu, Tooltip as Tooltip$1, Space, Button, ConfigProvider, Popover, Card as Card$2, Row, Col, Tabs, notification, Form, Switch, Segmented, Table, Progress, Statistic, message, Checkbox, List as List$1, InputNumber, Upload, Dropdown, Slider, Result, DatePicker, Radio, Empty } from 'antd';
5
5
  import * as AntIcons from '@ant-design/icons';
6
- import { LoadingOutlined, ExclamationCircleFilled, CloseCircleFilled, CheckCircleFilled, PlusOutlined, ClearOutlined, MinusOutlined, CaretDownOutlined, CaretRightOutlined, InfoCircleOutlined, SearchOutlined, EyeOutlined, EyeInvisibleOutlined, CopyOutlined, WarningOutlined, MoreOutlined, DownOutlined, QuestionCircleOutlined, CheckOutlined, CloseOutlined, BugOutlined, EllipsisOutlined, PoweroffOutlined, FullscreenExitOutlined, FullscreenOutlined, SettingOutlined, ReloadOutlined } from '@ant-design/icons';
6
+ import { LoadingOutlined, ExclamationCircleFilled, CloseCircleFilled, CheckCircleFilled, PlusOutlined, ClearOutlined, MinusOutlined, CaretDownOutlined, CaretRightOutlined, InfoCircleOutlined, SearchOutlined, EyeOutlined, EyeInvisibleOutlined, CopyOutlined, InboxOutlined, DeleteOutlined, WarningOutlined, MoreOutlined, DownOutlined, QuestionCircleOutlined, CheckOutlined, CloseOutlined, BugOutlined, EllipsisOutlined, PoweroffOutlined, FullscreenExitOutlined, FullscreenOutlined, SettingOutlined, ReloadOutlined } from '@ant-design/icons';
7
7
  import { useNavigate, useSearchParams, Link, useLocation, useParams } from 'react-router-dom';
8
8
  import { useQuery, useQueries, useQueryClient } from '@tanstack/react-query';
9
9
  import RFB from 'novnc-next';
@@ -78551,7 +78551,7 @@ const TolerationsModal = ({
78551
78551
  };
78552
78552
 
78553
78553
  const LazyEnrichedTableModal = lazy(
78554
- () => import('./index-DlJkWTNK.mjs').then((mod) => ({ default: mod.EnrichedTableModal }))
78554
+ () => import('./index-DcEC4xll.mjs').then((mod) => ({ default: mod.EnrichedTableModal }))
78555
78555
  );
78556
78556
  const renderActiveType = (activeType, extraProps) => {
78557
78557
  if (!activeType) return null;
@@ -79597,7 +79597,9 @@ const ACTION_REQUIRED_PERMISSIONS = {
79597
79597
  deleteChildren: { verb: "delete" },
79598
79598
  rerunLast: { verb: "create" },
79599
79599
  drain: { verb: "patch" },
79600
- rollback: { verb: "patch" }
79600
+ rollback: { verb: "patch" },
79601
+ downloadAsFiles: { verb: "get" },
79602
+ createFromFiles: { verb: "create" }
79601
79603
  };
79602
79604
 
79603
79605
  const IconWrapper = styled.span`
@@ -79768,6 +79770,74 @@ const buildDeleteChildrenData = (action, ctx) => {
79768
79770
  childResourceName: childResourceNamePrepared
79769
79771
  };
79770
79772
  };
79773
+ const generateDnsCompliantName = (prefix, maxLength = 63) => {
79774
+ const timestamp = Date.now();
79775
+ const randomHex = Math.random().toString(16).substring(2, 6);
79776
+ const suffix = `-${timestamp}-${randomHex}`;
79777
+ const truncatedPrefix = prefix.substring(0, maxLength - suffix.length);
79778
+ return `${truncatedPrefix}${suffix}`.toLowerCase().replace(/[^a-z0-9-]/g, "-");
79779
+ };
79780
+ const JOB_MANAGED_LABEL_KEYS = [
79781
+ "controller-uid",
79782
+ "job-name",
79783
+ "batch.kubernetes.io/controller-uid",
79784
+ "batch.kubernetes.io/job-name"
79785
+ ];
79786
+ const stripManagedJobLabels = (labels) => {
79787
+ if (!labels || typeof labels !== "object" || Array.isArray(labels)) {
79788
+ return void 0;
79789
+ }
79790
+ const cleaned = { ...labels };
79791
+ JOB_MANAGED_LABEL_KEYS.forEach((key) => delete cleaned[key]);
79792
+ return Object.keys(cleaned).length > 0 ? cleaned : void 0;
79793
+ };
79794
+ const stripMetadataForRerun = (sourceObj, sourceJobName) => {
79795
+ let normalizedSourceObj = sourceObj;
79796
+ if (_$1.isPlainObject(_$1.get(sourceObj, "spec"))) {
79797
+ normalizedSourceObj = sourceObj;
79798
+ } else if (_$1.isPlainObject(sourceObj) && _$1.isPlainObject(_$1.get(sourceObj, "template"))) {
79799
+ normalizedSourceObj = { spec: sourceObj };
79800
+ }
79801
+ const copy = JSON.parse(JSON.stringify(normalizedSourceObj));
79802
+ const oldMeta = copy.metadata ?? {};
79803
+ const cleanedMetadataLabels = stripManagedJobLabels(oldMeta.labels);
79804
+ copy.metadata = {
79805
+ ...oldMeta.namespace ? { namespace: oldMeta.namespace } : {},
79806
+ ...cleanedMetadataLabels ? { labels: cleanedMetadataLabels } : {},
79807
+ ...oldMeta.annotations ? { annotations: oldMeta.annotations } : {},
79808
+ generateName: `${sourceJobName}-rerun-`
79809
+ };
79810
+ const spec = _$1.get(copy, "spec");
79811
+ if (_$1.isPlainObject(spec)) {
79812
+ const specObj = spec;
79813
+ delete specObj.selector;
79814
+ delete specObj.manualSelector;
79815
+ }
79816
+ const templateLabels = _$1.get(copy, "spec.template.metadata.labels");
79817
+ if (_$1.isPlainObject(templateLabels)) {
79818
+ const cleanedTemplateLabels = stripManagedJobLabels(templateLabels);
79819
+ if (cleanedTemplateLabels) {
79820
+ _$1.set(copy, "spec.template.metadata.labels", cleanedTemplateLabels);
79821
+ } else {
79822
+ _$1.unset(copy, "spec.template.metadata.labels");
79823
+ }
79824
+ }
79825
+ delete copy.status;
79826
+ return copy;
79827
+ };
79828
+ const MAX_FAILED_PODS_SHOWN = 5;
79829
+ const buildDrainFailureDescription = ({ drained, failed, skipped }) => {
79830
+ const lines = [`Evicted ${drained}, skipped ${skipped}, failed ${failed.length}`];
79831
+ const shown = failed.slice(0, MAX_FAILED_PODS_SHOWN);
79832
+ shown.forEach((pod) => {
79833
+ lines.push(React__default.createElement("br", null), `${pod.namespace}/${pod.name}: ${pod.error}`);
79834
+ });
79835
+ if (failed.length > MAX_FAILED_PODS_SHOWN) {
79836
+ lines.push(React__default.createElement("br", null), `+${failed.length - MAX_FAILED_PODS_SHOWN} more`);
79837
+ }
79838
+ return React__default.createElement(React__default.Fragment, null, ...lines);
79839
+ };
79840
+
79771
79841
  const handleEditAction = (action, ctx, fullPath, navigate) => {
79772
79842
  const clusterPrepared = parseAll({ text: action.props.cluster, ...ctx });
79773
79843
  const namespacePrepared = action.props.namespace ? parseAll({ text: action.props.namespace, ...ctx }) : void 0;
@@ -79853,56 +79923,47 @@ const handleOpenKubeletConfigAction = (action, ctx, setActiveAction, setModalOpe
79853
79923
  });
79854
79924
  setModalOpen(true);
79855
79925
  };
79856
- const generateDnsCompliantName = (prefix, maxLength = 63) => {
79857
- const timestamp = Date.now();
79858
- const randomHex = Math.random().toString(16).substring(2, 6);
79859
- const suffix = `-${timestamp}-${randomHex}`;
79860
- const truncatedPrefix = prefix.substring(0, maxLength - suffix.length);
79861
- return `${truncatedPrefix}${suffix}`.toLowerCase().replace(/[^a-z0-9-]/g, "-");
79862
- };
79863
- const JOB_MANAGED_LABEL_KEYS = [
79864
- "controller-uid",
79865
- "job-name",
79866
- "batch.kubernetes.io/controller-uid",
79867
- "batch.kubernetes.io/job-name"
79868
- ];
79869
- const stripManagedJobLabels = (labels) => {
79870
- if (!labels || typeof labels !== "object" || Array.isArray(labels)) {
79871
- return void 0;
79926
+ const fireTriggerRunAction = (action, ctx, multiQueryData, { showSuccess, showError }) => {
79927
+ const createEndpointPrepared = parseAll({ text: action.props.createEndpoint, ...ctx });
79928
+ const cronJobNamePrepared = parseAll({ text: action.props.cronJobName, ...ctx });
79929
+ const jobTemplateObj = resolveObjectFromTemplate(action.props.jobTemplate, multiQueryData);
79930
+ if (!jobTemplateObj) {
79931
+ showError("Trigger run", new Error("Could not resolve job template from resource data"));
79932
+ return;
79872
79933
  }
79873
- const cleaned = { ...labels };
79874
- JOB_MANAGED_LABEL_KEYS.forEach((key) => delete cleaned[key]);
79875
- return Object.keys(cleaned).length > 0 ? cleaned : void 0;
79876
- };
79877
- const stripMetadataForRerun = (sourceObj, sourceJobName) => {
79878
- const normalizedSourceObj = _$1.isPlainObject(_$1.get(sourceObj, "spec")) ? sourceObj : _$1.isPlainObject(sourceObj) && _$1.isPlainObject(_$1.get(sourceObj, "template")) ? { spec: sourceObj } : sourceObj;
79879
- const copy = JSON.parse(JSON.stringify(normalizedSourceObj));
79880
- const oldMeta = copy.metadata ?? {};
79881
- const cleanedMetadataLabels = stripManagedJobLabels(oldMeta.labels);
79882
- copy.metadata = {
79883
- ...oldMeta.namespace ? { namespace: oldMeta.namespace } : {},
79884
- ...cleanedMetadataLabels ? { labels: cleanedMetadataLabels } : {},
79885
- ...oldMeta.annotations ? { annotations: oldMeta.annotations } : {},
79886
- generateName: `${sourceJobName}-rerun-`
79934
+ const jobName = generateDnsCompliantName(`${cronJobNamePrepared}-manual`);
79935
+ const namespaceParsed = cronJobNamePrepared ? _$1.get(jobTemplateObj, ["metadata", "namespace"]) : void 0;
79936
+ const body = {
79937
+ apiVersion: "batch/v1",
79938
+ kind: "Job",
79939
+ metadata: {
79940
+ name: jobName,
79941
+ ...namespaceParsed ? { namespace: namespaceParsed } : {},
79942
+ annotations: {
79943
+ "cronjob.kubernetes.io/instantiate": "manual"
79944
+ }
79945
+ },
79946
+ spec: jobTemplateObj.spec
79887
79947
  };
79888
- const spec = _$1.get(copy, "spec");
79889
- if (_$1.isPlainObject(spec)) {
79890
- const specObj = spec;
79891
- delete specObj.selector;
79892
- delete specObj.manualSelector;
79893
- }
79894
- const templateLabels = _$1.get(copy, "spec.template.metadata.labels");
79895
- if (_$1.isPlainObject(templateLabels)) {
79896
- const cleanedTemplateLabels = stripManagedJobLabels(templateLabels);
79897
- if (cleanedTemplateLabels) {
79898
- _$1.set(copy, "spec.template.metadata.labels", cleanedTemplateLabels);
79899
- } else {
79900
- _$1.unset(copy, "spec.template.metadata.labels");
79948
+ const triggerLabel = `Trigger run for ${cronJobNamePrepared}`;
79949
+ createNewEntry({ endpoint: createEndpointPrepared, body }).then(() => showSuccess(triggerLabel)).catch((error) => {
79950
+ showError(triggerLabel, error);
79951
+ });
79952
+ };
79953
+ const handleDownloadAsFilesAction = (action, ctx, setActiveAction, setModalOpen) => {
79954
+ const endpointPrepared = parseAll({ text: action.props.endpoint, ...ctx });
79955
+ const namePrepared = parseAll({ text: action.props.name, ...ctx });
79956
+ setActiveAction({
79957
+ ...action,
79958
+ props: {
79959
+ ...action.props,
79960
+ endpoint: endpointPrepared,
79961
+ name: namePrepared
79901
79962
  }
79902
- }
79903
- delete copy.status;
79904
- return copy;
79963
+ });
79964
+ setModalOpen(true);
79905
79965
  };
79966
+
79906
79967
  const useScaleHandlers = (ctx, { showSuccess, showError }) => {
79907
79968
  const [scaleModalData, setScaleModalData] = useState(null);
79908
79969
  const [isScaleLoading, setIsScaleLoading] = useState(false);
@@ -79947,6 +80008,7 @@ const useScaleHandlers = (ctx, { showSuccess, showError }) => {
79947
80008
  };
79948
80009
  return { scaleModalData, isScaleLoading, handleScaleAction, handleScaleConfirm, handleScaleCancel };
79949
80010
  };
80011
+
79950
80012
  const useEvictHandlers = ({ showSuccess, showError }) => {
79951
80013
  const [evictModalData, setEvictModalData] = useState(null);
79952
80014
  const [isEvictLoading, setIsEvictLoading] = useState(false);
@@ -79968,6 +80030,7 @@ const useEvictHandlers = ({ showSuccess, showError }) => {
79968
80030
  };
79969
80031
  return { evictModalData, isEvictLoading, setEvictModalData, handleEvictConfirm, handleEvictCancel };
79970
80032
  };
80033
+
79971
80034
  const useRerunHandlers = (ctx, multiQueryData, { showSuccess, showError }) => {
79972
80035
  const [rerunModalData, setRerunModalData] = useState(null);
79973
80036
  const [isRerunLoading, setIsRerunLoading] = useState(false);
@@ -80003,18 +80066,7 @@ const useRerunHandlers = (ctx, multiQueryData, { showSuccess, showError }) => {
80003
80066
  };
80004
80067
  return { rerunModalData, isRerunLoading, handleRerunLastAction, handleRerunConfirm, handleRerunCancel };
80005
80068
  };
80006
- const MAX_FAILED_PODS_SHOWN = 5;
80007
- const buildDrainFailureDescription = ({ drained, failed, skipped }) => {
80008
- const lines = [`Evicted ${drained}, skipped ${skipped}, failed ${failed.length}`];
80009
- const shown = failed.slice(0, MAX_FAILED_PODS_SHOWN);
80010
- shown.forEach((pod) => {
80011
- lines.push(React__default.createElement("br", null), `${pod.namespace}/${pod.name}: ${pod.error}`);
80012
- });
80013
- if (failed.length > MAX_FAILED_PODS_SHOWN) {
80014
- lines.push(React__default.createElement("br", null), `+${failed.length - MAX_FAILED_PODS_SHOWN} more`);
80015
- }
80016
- return React__default.createElement(React__default.Fragment, null, ...lines);
80017
- };
80069
+
80018
80070
  const useDrainHandlers = (ctx, { showError }, notificationApi, invalidateMultiQuery) => {
80019
80071
  const [drainModalData, setDrainModalData] = useState(null);
80020
80072
  const [isDrainLoading, setIsDrainLoading] = useState(false);
@@ -80060,6 +80112,7 @@ const useDrainHandlers = (ctx, { showError }, notificationApi, invalidateMultiQu
80060
80112
  };
80061
80113
  return { drainModalData, isDrainLoading, handleDrainAction, handleDrainConfirm, handleDrainCancel };
80062
80114
  };
80115
+
80063
80116
  const useRollbackHandlers = (ctx, { showSuccess, showError }) => {
80064
80117
  const [rollbackModalData, setRollbackModalData] = useState(null);
80065
80118
  const [isRollbackLoading, setIsRollbackLoading] = useState(false);
@@ -80093,33 +80146,57 @@ const useRollbackHandlers = (ctx, { showSuccess, showError }) => {
80093
80146
  };
80094
80147
  return { rollbackModalData, isRollbackLoading, handleRollbackAction, handleRollbackConfirm, handleRollbackCancel };
80095
80148
  };
80096
- const fireTriggerRunAction = (action, ctx, multiQueryData, { showSuccess, showError }) => {
80097
- const createEndpointPrepared = parseAll({ text: action.props.createEndpoint, ...ctx });
80098
- const cronJobNamePrepared = parseAll({ text: action.props.cronJobName, ...ctx });
80099
- const jobTemplateObj = resolveObjectFromTemplate(action.props.jobTemplate, multiQueryData);
80100
- if (!jobTemplateObj) {
80101
- showError("Trigger run", new Error("Could not resolve job template from resource data"));
80102
- return;
80103
- }
80104
- const jobName = generateDnsCompliantName(`${cronJobNamePrepared}-manual`);
80105
- const namespaceParsed = cronJobNamePrepared ? _$1.get(jobTemplateObj, ["metadata", "namespace"]) : void 0;
80106
- const body = {
80107
- apiVersion: "batch/v1",
80108
- kind: "Job",
80109
- metadata: {
80110
- name: jobName,
80111
- ...namespaceParsed ? { namespace: namespaceParsed } : {},
80112
- annotations: {
80113
- "cronjob.kubernetes.io/instantiate": "manual"
80114
- }
80115
- },
80116
- spec: jobTemplateObj.spec
80149
+
80150
+ const useCreateFromFilesHandlers = (ctx, { showSuccess, showError }) => {
80151
+ const [createFromFilesModalData, setCreateFromFilesModalData] = useState(null);
80152
+ const [isCreateFromFilesLoading, setIsCreateFromFilesLoading] = useState(false);
80153
+ const handleCreateFromFilesAction = (action) => {
80154
+ const createEndpointPrepared = parseAll({ text: action.props.createEndpoint, ...ctx });
80155
+ const namespacePrepared = parseAll({ text: action.props.namespace, ...ctx });
80156
+ const apiVersionPrepared = action.props.apiVersion ? parseAll({ text: action.props.apiVersion, ...ctx }) : "v1";
80157
+ setCreateFromFilesModalData({
80158
+ createEndpoint: createEndpointPrepared,
80159
+ namespace: namespacePrepared,
80160
+ resourceKind: action.props.resourceKind,
80161
+ apiVersion: apiVersionPrepared
80162
+ });
80163
+ };
80164
+ const handleCreateFromFilesConfirm = (name, data, binaryData) => {
80165
+ if (!createFromFilesModalData) return;
80166
+ setIsCreateFromFilesLoading(true);
80167
+ const { createEndpoint, namespace, resourceKind, apiVersion } = createFromFilesModalData;
80168
+ const createLabel = `Create ${resourceKind} ${name}`;
80169
+ const body = {
80170
+ apiVersion,
80171
+ kind: resourceKind,
80172
+ metadata: { name, namespace }
80173
+ };
80174
+ if (Object.keys(data).length > 0) {
80175
+ body.data = data;
80176
+ }
80177
+ if (Object.keys(binaryData).length > 0) {
80178
+ body.binaryData = binaryData;
80179
+ }
80180
+ createNewEntry({ endpoint: createEndpoint, body }).then(() => showSuccess(createLabel)).catch((error) => {
80181
+ showError(createLabel, error);
80182
+ }).finally(() => {
80183
+ setIsCreateFromFilesLoading(false);
80184
+ setCreateFromFilesModalData(null);
80185
+ });
80186
+ };
80187
+ const handleCreateFromFilesCancel = () => {
80188
+ setCreateFromFilesModalData(null);
80189
+ setIsCreateFromFilesLoading(false);
80190
+ };
80191
+ return {
80192
+ createFromFilesModalData,
80193
+ isCreateFromFilesLoading,
80194
+ handleCreateFromFilesAction,
80195
+ handleCreateFromFilesConfirm,
80196
+ handleCreateFromFilesCancel
80117
80197
  };
80118
- const triggerLabel = `Trigger run for ${cronJobNamePrepared}`;
80119
- createNewEntry({ endpoint: createEndpointPrepared, body }).then(() => showSuccess(triggerLabel)).catch((error) => {
80120
- showError(triggerLabel, error);
80121
- });
80122
80198
  };
80199
+
80123
80200
  const useActionsDropdownHandlers = ({ replaceValues, multiQueryData }) => {
80124
80201
  const navigate = useNavigate();
80125
80202
  const location = useLocation();
@@ -80172,6 +80249,13 @@ const useActionsDropdownHandlers = ({ replaceValues, multiQueryData }) => {
80172
80249
  invalidateMultiQuery
80173
80250
  );
80174
80251
  const { rollbackModalData, isRollbackLoading, handleRollbackAction, handleRollbackConfirm, handleRollbackCancel } = useRollbackHandlers(ctx, notificationCallbacks);
80252
+ const {
80253
+ createFromFilesModalData,
80254
+ isCreateFromFilesLoading,
80255
+ handleCreateFromFilesAction,
80256
+ handleCreateFromFilesConfirm,
80257
+ handleCreateFromFilesCancel
80258
+ } = useCreateFromFilesHandlers(ctx, notificationCallbacks);
80175
80259
  const handleDeleteChildrenAction = (action) => {
80176
80260
  try {
80177
80261
  const data = buildDeleteChildrenData(action, ctx);
@@ -80186,57 +80270,59 @@ const useActionsDropdownHandlers = ({ replaceValues, multiQueryData }) => {
80186
80270
  invalidateMultiQuery();
80187
80271
  };
80188
80272
  const handleActionClick = (action) => {
80189
- if (action.type === "edit") {
80190
- handleEditAction(action, ctx, fullPath, navigate);
80191
- return;
80192
- }
80193
- if (action.type === "delete") {
80194
- handleDeleteAction(action, ctx, setDeleteModalData);
80195
- return;
80196
- }
80197
- if (action.type === "cordon" || action.type === "uncordon" || action.type === "suspend" || action.type === "resume") {
80198
- handlePatchActions(action, ctx, showSuccess, showError);
80199
- return;
80200
- }
80201
- if (action.type === "rolloutRestart") {
80202
- handleRolloutRestartAction(action, ctx, showSuccess, showError);
80203
- return;
80204
- }
80205
- if (action.type === "evict") {
80206
- const evictData = buildEvictModalData(action.props, ctx);
80207
- setEvictModalData(evictData);
80208
- return;
80209
- }
80210
- if (action.type === "openKubeletConfig") {
80211
- handleOpenKubeletConfigAction(action, ctx, setActiveAction, setModalOpen);
80212
- return;
80213
- }
80214
- if (action.type === "scale") {
80215
- handleScaleAction(action);
80216
- return;
80217
- }
80218
- if (action.type === "triggerRun") {
80219
- fireTriggerRunAction(action, ctx, multiQueryData, notificationCallbacks);
80220
- return;
80221
- }
80222
- if (action.type === "deleteChildren") {
80223
- handleDeleteChildrenAction(action);
80224
- return;
80225
- }
80226
- if (action.type === "rerunLast") {
80227
- handleRerunLastAction(action);
80228
- return;
80229
- }
80230
- if (action.type === "drain") {
80231
- handleDrainAction(action);
80232
- return;
80233
- }
80234
- if (action.type === "rollback") {
80235
- handleRollbackAction(action);
80236
- return;
80273
+ switch (action.type) {
80274
+ case "edit":
80275
+ handleEditAction(action, ctx, fullPath, navigate);
80276
+ return;
80277
+ case "delete":
80278
+ handleDeleteAction(action, ctx, setDeleteModalData);
80279
+ return;
80280
+ case "cordon":
80281
+ case "uncordon":
80282
+ case "suspend":
80283
+ case "resume":
80284
+ handlePatchActions(action, ctx, showSuccess, showError);
80285
+ return;
80286
+ case "rolloutRestart":
80287
+ handleRolloutRestartAction(action, ctx, showSuccess, showError);
80288
+ return;
80289
+ case "evict": {
80290
+ const evictData = buildEvictModalData(action.props, ctx);
80291
+ setEvictModalData(evictData);
80292
+ return;
80293
+ }
80294
+ case "openKubeletConfig":
80295
+ handleOpenKubeletConfigAction(action, ctx, setActiveAction, setModalOpen);
80296
+ return;
80297
+ case "scale":
80298
+ handleScaleAction(action);
80299
+ return;
80300
+ case "triggerRun":
80301
+ fireTriggerRunAction(action, ctx, multiQueryData, notificationCallbacks);
80302
+ return;
80303
+ case "deleteChildren":
80304
+ handleDeleteChildrenAction(action);
80305
+ return;
80306
+ case "rerunLast":
80307
+ handleRerunLastAction(action);
80308
+ return;
80309
+ case "drain":
80310
+ handleDrainAction(action);
80311
+ return;
80312
+ case "rollback":
80313
+ handleRollbackAction(action);
80314
+ return;
80315
+ case "downloadAsFiles":
80316
+ handleDownloadAsFilesAction(action, ctx, setActiveAction, setModalOpen);
80317
+ return;
80318
+ case "createFromFiles":
80319
+ handleCreateFromFilesAction(action);
80320
+ return;
80321
+ default: {
80322
+ setActiveAction(action);
80323
+ setModalOpen(true);
80324
+ }
80237
80325
  }
80238
- setActiveAction(action);
80239
- setModalOpen(true);
80240
80326
  };
80241
80327
  const handleCloseModal = () => {
80242
80328
  setModalOpen(false);
@@ -80281,7 +80367,11 @@ const useActionsDropdownHandlers = ({ replaceValues, multiQueryData }) => {
80281
80367
  handleDrainConfirm,
80282
80368
  handleDrainCancel,
80283
80369
  handleRollbackConfirm,
80284
- handleRollbackCancel
80370
+ handleRollbackCancel,
80371
+ createFromFilesModalData,
80372
+ isCreateFromFilesLoading,
80373
+ handleCreateFromFilesConfirm,
80374
+ handleCreateFromFilesCancel
80285
80375
  };
80286
80376
  };
80287
80377
 
@@ -80445,6 +80535,146 @@ const OpenKubeletConfigModal = ({ open, onClose, props }) => {
80445
80535
  );
80446
80536
  };
80447
80537
 
80538
+ const getDataEntries = (resource) => {
80539
+ const entries = [];
80540
+ const data = resource.data;
80541
+ const binaryData = resource.binaryData;
80542
+ if (data) {
80543
+ Object.keys(data).forEach((key) => {
80544
+ entries.push({ key, isBinary: false });
80545
+ });
80546
+ }
80547
+ if (binaryData) {
80548
+ Object.keys(binaryData).forEach((key) => {
80549
+ entries.push({ key, isBinary: true });
80550
+ });
80551
+ }
80552
+ return entries;
80553
+ };
80554
+ const decodeBase64 = (value) => {
80555
+ const binaryString = atob(value);
80556
+ const bytes = new Uint8Array(binaryString.length);
80557
+ for (let i = 0; i < binaryString.length; i += 1) {
80558
+ bytes[i] = binaryString.charCodeAt(i);
80559
+ }
80560
+ return bytes;
80561
+ };
80562
+ const triggerFileDownload = (filename, content) => {
80563
+ const blob = typeof content === "string" ? new Blob([content], { type: "text/plain" }) : new Blob([content]);
80564
+ const url = URL.createObjectURL(blob);
80565
+ const a = document.createElement("a");
80566
+ a.href = url;
80567
+ a.download = filename;
80568
+ document.body.appendChild(a);
80569
+ a.click();
80570
+ document.body.removeChild(a);
80571
+ URL.revokeObjectURL(url);
80572
+ };
80573
+ const DownloadAsFilesModal = ({
80574
+ open,
80575
+ onClose,
80576
+ endpoint,
80577
+ resourceKind,
80578
+ name
80579
+ }) => {
80580
+ const [selectedKeys, setSelectedKeys] = useState([]);
80581
+ const { data, isLoading, isError, error } = useDirectUnknownResource({
80582
+ uri: endpoint,
80583
+ queryKey: ["download-as-files", endpoint],
80584
+ refetchInterval: false,
80585
+ isEnabled: open && !!endpoint && endpoint !== "-"
80586
+ });
80587
+ const entries = useMemo(() => data ? getDataEntries(data) : [], [data]);
80588
+ const allKeys = useMemo(() => entries.map((e) => e.key), [entries]);
80589
+ const handleSelectAll = (checked) => {
80590
+ setSelectedKeys(checked ? allKeys : []);
80591
+ };
80592
+ const handleToggleKey = (key, checked) => {
80593
+ setSelectedKeys((prev) => checked ? [...prev, key] : prev.filter((k) => k !== key));
80594
+ };
80595
+ const handleDownload = () => {
80596
+ if (!data) return;
80597
+ const dataMap = data.data ?? {};
80598
+ const binaryDataMap = data.binaryData ?? {};
80599
+ const isSecret = resourceKind === "Secret";
80600
+ selectedKeys.forEach((key) => {
80601
+ if (binaryDataMap[key] !== void 0) {
80602
+ triggerFileDownload(key, decodeBase64(binaryDataMap[key]));
80603
+ } else if (dataMap[key] !== void 0) {
80604
+ const content = isSecret ? decodeBase64(dataMap[key]) : dataMap[key];
80605
+ triggerFileDownload(key, content);
80606
+ }
80607
+ });
80608
+ onClose();
80609
+ };
80610
+ const isAllSelected = allKeys.length > 0 && selectedKeys.length === allKeys.length;
80611
+ const isIndeterminate = selectedKeys.length > 0 && selectedKeys.length < allKeys.length;
80612
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(
80613
+ Modal,
80614
+ {
80615
+ title: `Download files from «${name}»`,
80616
+ open,
80617
+ onOk: handleDownload,
80618
+ onCancel: onClose,
80619
+ okText: "Download",
80620
+ okButtonProps: { disabled: selectedKeys.length === 0 },
80621
+ width: 520,
80622
+ children: [
80623
+ isLoading && /* @__PURE__ */ jsxRuntimeExports.jsx(Spin, {}),
80624
+ isError && /* @__PURE__ */ jsxRuntimeExports.jsx(
80625
+ Alert,
80626
+ {
80627
+ type: "error",
80628
+ showIcon: true,
80629
+ message: "Failed to load resource",
80630
+ description: error instanceof Error ? error.message : "Unknown error"
80631
+ }
80632
+ ),
80633
+ !isLoading && !isError && entries.length === 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(Typography.Text, { type: "secondary", children: [
80634
+ "No data entries found in this ",
80635
+ resourceKind,
80636
+ "."
80637
+ ] }),
80638
+ !isLoading && !isError && entries.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
80639
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { marginBottom: 8 }, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
80640
+ Checkbox,
80641
+ {
80642
+ checked: isAllSelected,
80643
+ indeterminate: isIndeterminate,
80644
+ onChange: (e) => handleSelectAll(e.target.checked),
80645
+ children: [
80646
+ "Select all (",
80647
+ entries.length,
80648
+ ")"
80649
+ ]
80650
+ }
80651
+ ) }),
80652
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
80653
+ List$1,
80654
+ {
80655
+ size: "small",
80656
+ bordered: true,
80657
+ dataSource: entries,
80658
+ style: { maxHeight: 400, overflow: "auto" },
80659
+ renderItem: (entry) => /* @__PURE__ */ jsxRuntimeExports.jsx(List$1.Item, { style: { padding: "4px 12px" }, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
80660
+ Checkbox,
80661
+ {
80662
+ checked: selectedKeys.includes(entry.key),
80663
+ onChange: (e) => handleToggleKey(entry.key, e.target.checked),
80664
+ children: [
80665
+ entry.key,
80666
+ entry.isBinary && /* @__PURE__ */ jsxRuntimeExports.jsx(Typography.Text, { type: "secondary", style: { marginLeft: 8 }, children: "(binary)" })
80667
+ ]
80668
+ }
80669
+ ) })
80670
+ }
80671
+ )
80672
+ ] })
80673
+ ]
80674
+ }
80675
+ );
80676
+ };
80677
+
80448
80678
  const renderActionModal = (action, extraProps) => {
80449
80679
  switch (action.type) {
80450
80680
  case "edit":
@@ -80474,7 +80704,18 @@ const renderActionModal = (action, extraProps) => {
80474
80704
  case "rerunLast":
80475
80705
  case "drain":
80476
80706
  case "rollback":
80707
+ case "createFromFiles":
80477
80708
  return null;
80709
+ case "downloadAsFiles":
80710
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
80711
+ DownloadAsFilesModal,
80712
+ {
80713
+ ...extraProps,
80714
+ endpoint: action.props.endpoint,
80715
+ resourceKind: action.props.resourceKind,
80716
+ name: action.props.name
80717
+ }
80718
+ );
80478
80719
  default: {
80479
80720
  const _exhaustive = action;
80480
80721
  return _exhaustive;
@@ -80529,6 +80770,169 @@ const ScaleModal = ({ open, onClose, onConfirm, currentReplicas, name, isLoading
80529
80770
  );
80530
80771
  };
80531
80772
 
80773
+ const isValidUtf8Text = (bytes) => {
80774
+ try {
80775
+ const decoded = new TextDecoder("utf-8", { fatal: true }).decode(bytes);
80776
+ return !decoded.includes("\0");
80777
+ } catch {
80778
+ return false;
80779
+ }
80780
+ };
80781
+ const arrayBufferToBase64 = (buffer) => {
80782
+ const bytes = new Uint8Array(buffer);
80783
+ let binary = "";
80784
+ for (let i = 0; i < bytes.length; i += 1) {
80785
+ binary += String.fromCharCode(bytes[i]);
80786
+ }
80787
+ return btoa(binary);
80788
+ };
80789
+ const CreateFromFilesModal = ({
80790
+ open,
80791
+ onClose,
80792
+ onConfirm,
80793
+ resourceKind,
80794
+ namespace,
80795
+ isLoading
80796
+ }) => {
80797
+ const [resourceName, setResourceName] = useState("");
80798
+ const [fileEntries, setFileEntries] = useState([]);
80799
+ const handleBeforeUpload = (file) => {
80800
+ const reader = new FileReader();
80801
+ reader.onload = () => {
80802
+ const buffer = reader.result;
80803
+ const bytes = new Uint8Array(buffer);
80804
+ const isBinary = !isValidUtf8Text(bytes);
80805
+ let content;
80806
+ if (resourceKind === "Secret") {
80807
+ content = arrayBufferToBase64(buffer);
80808
+ } else if (isBinary) {
80809
+ content = arrayBufferToBase64(buffer);
80810
+ } else {
80811
+ content = new TextDecoder("utf-8").decode(bytes);
80812
+ }
80813
+ setFileEntries((prev) => [
80814
+ ...prev,
80815
+ {
80816
+ uid: file.uid,
80817
+ originalName: file.name,
80818
+ keyName: file.name,
80819
+ content,
80820
+ isBinary: resourceKind === "Secret" ? false : isBinary
80821
+ }
80822
+ ]);
80823
+ };
80824
+ reader.readAsArrayBuffer(file);
80825
+ return false;
80826
+ };
80827
+ const handleRemoveFile = (uid) => {
80828
+ setFileEntries((prev) => prev.filter((e) => e.uid !== uid));
80829
+ };
80830
+ const handleKeyNameChange = (uid, newKeyName) => {
80831
+ setFileEntries((prev) => prev.map((e) => e.uid === uid ? { ...e, keyName: newKeyName } : e));
80832
+ };
80833
+ const handleConfirm = () => {
80834
+ const trimmedResourceName = resourceName.trim();
80835
+ const data = {};
80836
+ const binaryData = {};
80837
+ fileEntries.forEach((entry) => {
80838
+ const keyName = entry.keyName.trim();
80839
+ if (entry.isBinary) {
80840
+ binaryData[keyName] = entry.content;
80841
+ } else {
80842
+ data[keyName] = entry.content;
80843
+ }
80844
+ });
80845
+ onConfirm(trimmedResourceName, data, binaryData);
80846
+ };
80847
+ const handleClose = () => {
80848
+ setResourceName("");
80849
+ setFileEntries([]);
80850
+ onClose();
80851
+ };
80852
+ const hasEmptyKeyNames = fileEntries.some((e) => !e.keyName.trim());
80853
+ const hasDuplicateKeyNames = new Set(fileEntries.map((e) => e.keyName.trim())).size !== fileEntries.length;
80854
+ const isValid = resourceName.trim() && fileEntries.length > 0 && !hasEmptyKeyNames && !hasDuplicateKeyNames;
80855
+ const columns = [
80856
+ {
80857
+ title: "File",
80858
+ dataIndex: "originalName",
80859
+ key: "originalName",
80860
+ width: "35%",
80861
+ render: (text, record) => /* @__PURE__ */ jsxRuntimeExports.jsxs(Space, { children: [
80862
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Typography.Text, { ellipsis: true, style: { maxWidth: 150 }, children: text }),
80863
+ record.isBinary && /* @__PURE__ */ jsxRuntimeExports.jsx(Typography.Text, { type: "secondary", children: "(binary)" })
80864
+ ] })
80865
+ },
80866
+ {
80867
+ title: "Key name",
80868
+ dataIndex: "keyName",
80869
+ key: "keyName",
80870
+ render: (_, record) => /* @__PURE__ */ jsxRuntimeExports.jsx(
80871
+ Input,
80872
+ {
80873
+ size: "small",
80874
+ value: record.keyName,
80875
+ onChange: (e) => handleKeyNameChange(record.uid, e.target.value),
80876
+ status: !record.keyName.trim() ? "error" : void 0
80877
+ }
80878
+ )
80879
+ },
80880
+ {
80881
+ title: "",
80882
+ key: "actions",
80883
+ width: 40,
80884
+ render: (_, record) => /* @__PURE__ */ jsxRuntimeExports.jsx(DeleteOutlined, { style: { color: "#ff4d4f", cursor: "pointer" }, onClick: () => handleRemoveFile(record.uid) })
80885
+ }
80886
+ ];
80887
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
80888
+ Modal,
80889
+ {
80890
+ title: `Create ${resourceKind} from files`,
80891
+ open,
80892
+ onOk: handleConfirm,
80893
+ onCancel: handleClose,
80894
+ okText: "Create",
80895
+ confirmLoading: isLoading,
80896
+ okButtonProps: { disabled: !isValid },
80897
+ width: 600,
80898
+ children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Space, { direction: "vertical", style: { width: "100%" }, size: "middle", children: [
80899
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
80900
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Typography.Text, { strong: true, children: "Name" }),
80901
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
80902
+ Input,
80903
+ {
80904
+ placeholder: `${resourceKind.toLowerCase()}-name`,
80905
+ value: resourceName,
80906
+ onChange: (e) => setResourceName(e.target.value),
80907
+ style: { marginTop: 4 }
80908
+ }
80909
+ )
80910
+ ] }),
80911
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
80912
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Typography.Text, { strong: true, children: "Namespace" }),
80913
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Input, { value: namespace, disabled: true, style: { marginTop: 4 } })
80914
+ ] }),
80915
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(Upload.Dragger, { multiple: true, beforeUpload: handleBeforeUpload, showUploadList: false, children: [
80916
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "ant-upload-drag-icon", children: /* @__PURE__ */ jsxRuntimeExports.jsx(InboxOutlined, {}) }),
80917
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "ant-upload-text", children: "Click or drag files to add" })
80918
+ ] }),
80919
+ fileEntries.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(
80920
+ Table,
80921
+ {
80922
+ dataSource: fileEntries,
80923
+ columns,
80924
+ rowKey: "uid",
80925
+ size: "small",
80926
+ pagination: false,
80927
+ scroll: { y: 300 }
80928
+ }
80929
+ ),
80930
+ hasDuplicateKeyNames && /* @__PURE__ */ jsxRuntimeExports.jsx(Typography.Text, { type: "danger", children: "Key names must be unique." })
80931
+ ] })
80932
+ }
80933
+ );
80934
+ };
80935
+
80532
80936
  const ActionsDropdown = ({ data, children }) => {
80533
80937
  const { buttonText = "Actions", buttonVariant = "default", containerStyle, actions, permissions } = data;
80534
80938
  const { data: multiQueryData, isLoading: isMultiQueryLoading, isError: isMultiQueryError, errors } = useMultiQuery();
@@ -80578,7 +80982,11 @@ const ActionsDropdown = ({ data, children }) => {
80578
80982
  handleDrainConfirm,
80579
80983
  handleDrainCancel,
80580
80984
  handleRollbackConfirm,
80581
- handleRollbackCancel
80985
+ handleRollbackCancel,
80986
+ createFromFilesModalData,
80987
+ isCreateFromFilesLoading,
80988
+ handleCreateFromFilesConfirm,
80989
+ handleCreateFromFilesCancel
80582
80990
  } = useActionsDropdownHandlers({
80583
80991
  replaceValues,
80584
80992
  multiQueryData: safeMultiQueryData
@@ -80675,6 +81083,17 @@ const ActionsDropdown = ({ data, children }) => {
80675
81083
  children: "This will revert the resource to its previous revision."
80676
81084
  }
80677
81085
  ),
81086
+ createFromFilesModalData && /* @__PURE__ */ jsxRuntimeExports.jsx(
81087
+ CreateFromFilesModal,
81088
+ {
81089
+ open: true,
81090
+ onClose: handleCreateFromFilesCancel,
81091
+ onConfirm: handleCreateFromFilesConfirm,
81092
+ resourceKind: createFromFilesModalData.resourceKind,
81093
+ namespace: createFromFilesModalData.namespace,
81094
+ isLoading: isCreateFromFilesLoading
81095
+ }
81096
+ ),
80678
81097
  children
80679
81098
  ] });
80680
81099
  };
@@ -80935,15 +81354,35 @@ const getEnrichedColumns = ({
80935
81354
  const possibleCustomTypeWithProps = additionalPrinterColumnsKeyTypeProps && el.key ? additionalPrinterColumnsKeyTypeProps[el.key.toString()] : void 0;
80936
81355
  const useFactorySearch = possibleCustomTypeWithProps?.type === "factory";
80937
81356
  const colKey = el.key != null && String(el.key) || (Array.isArray(el.dataIndex) ? el.dataIndex.join(".") : String(el.dataIndex ?? colIndex));
81357
+ const getCellTextFromRecord = (record) => {
81358
+ const { dataIndex } = el;
81359
+ if (!dataIndex) return "";
81360
+ const entry = Array.isArray(dataIndex) ? lodashExports.get(record, dataIndex) : record?.[dataIndex];
81361
+ if (entry === null || entry === void 0) return "";
81362
+ if (typeof entry === "string") return entry.trim().toLowerCase();
81363
+ if (typeof entry === "number" || typeof entry === "boolean") return String(entry).toLowerCase();
81364
+ if (Array.isArray(entry))
81365
+ return entry.map((item) => String(item)).join(", ").trim().toLowerCase();
81366
+ if (typeof entry === "object") return JSON.stringify(entry).trim().toLowerCase();
81367
+ return String(entry).trim().toLowerCase();
81368
+ };
80938
81369
  const getCellTextFromDOM = (record) => {
81370
+ if (typeof document === "undefined") return "";
80939
81371
  const rowKey = getRowKey(record);
80940
- const selector = `td[data-rowkey="${String(rowKey)}"][data-colkey="${colKey}"]`;
80941
- const cell = document.querySelector(selector);
80942
- if (!cell) return "";
80943
- return (cell.innerText || cell.textContent || "").trim().toLowerCase();
81372
+ const rowKeyStr = String(rowKey);
81373
+ const colKeyStr = String(colKey);
81374
+ const cells = document.querySelectorAll("td[data-rowkey][data-colkey]");
81375
+ for (let i = 0; i < cells.length; i += 1) {
81376
+ const cell = cells[i];
81377
+ if (cell.getAttribute("data-rowkey") === rowKeyStr && cell.getAttribute("data-colkey") === colKeyStr) {
81378
+ return (cell.innerText || cell.textContent || "").trim().toLowerCase();
81379
+ }
81380
+ }
81381
+ return "";
80944
81382
  };
81383
+ const getComparableCellText = (record) => getCellTextFromDOM(record) || getCellTextFromRecord(record);
80945
81384
  const getMemoryInBytes = (record) => {
80946
- const text = getCellTextFromDOM(record);
81385
+ const text = getComparableCellText(record);
80947
81386
  if (!text) return 0;
80948
81387
  const parsed = parseValueWithUnit(text);
80949
81388
  if (!parsed) return 0;
@@ -80954,7 +81393,7 @@ const getEnrichedColumns = ({
80954
81393
  return parsed.value;
80955
81394
  };
80956
81395
  const getCpuInCores = (record) => {
80957
- const text = getCellTextFromDOM(record);
81396
+ const text = getComparableCellText(record);
80958
81397
  if (!text) return 0;
80959
81398
  const parsed = parseCoresWithUnit(text);
80960
81399
  if (!parsed) return 0;
@@ -81031,7 +81470,7 @@ const getEnrichedColumns = ({
81031
81470
  return false;
81032
81471
  }
81033
81472
  if (useFactorySearch) {
81034
- const text = getCellTextFromDOM(record);
81473
+ const text = getComparableCellText(record);
81035
81474
  return text.includes(String(value).toLowerCase());
81036
81475
  }
81037
81476
  const { dataIndex } = el;
@@ -81066,8 +81505,8 @@ const getEnrichedColumns = ({
81066
81505
  return safeNumericCompare(aCores, bCores);
81067
81506
  }
81068
81507
  if (useFactorySearch) {
81069
- const aText = getCellTextFromDOM(a);
81070
- const bText = getCellTextFromDOM(b);
81508
+ const aText = getComparableCellText(a);
81509
+ const bText = getComparableCellText(b);
81071
81510
  return aText.localeCompare(bText);
81072
81511
  }
81073
81512
  const { dataIndex } = el;
@@ -81307,6 +81746,99 @@ const EnrichedTable = ({
81307
81746
  );
81308
81747
  };
81309
81748
 
81749
+ const ClusterListTable = ({
81750
+ theme,
81751
+ dataSource,
81752
+ columns,
81753
+ pathToNavigate,
81754
+ recordKeysForNavigation,
81755
+ navigationSettings,
81756
+ tableProps
81757
+ }) => {
81758
+ const navigate = useNavigate();
81759
+ if (!columns) {
81760
+ return null;
81761
+ }
81762
+ const rowKey = (record) => record.key;
81763
+ const enrichedColumns = getEnrichedColumns({
81764
+ columns,
81765
+ theme,
81766
+ getRowKey: rowKey
81767
+ });
81768
+ if (!enrichedColumns) {
81769
+ return null;
81770
+ }
81771
+ const showTotal = (total) => `Total: ${total}`;
81772
+ const tryGetPathFromNavigationResource = async (clusterName) => {
81773
+ const resolvedCluster = clusterName;
81774
+ const resolvedApiGroup = navigationSettings?.apiGroup;
81775
+ const resolvedApiVersion = navigationSettings?.apiVersion;
81776
+ const resolvedPlural = navigationSettings?.plural;
81777
+ const resolvedResourceName = navigationSettings?.resourceName;
81778
+ if (!resolvedCluster || !resolvedApiGroup || !resolvedApiVersion || !resolvedPlural || !resolvedResourceName) {
81779
+ return void 0;
81780
+ }
81781
+ try {
81782
+ const { data } = await axios.get(
81783
+ `/api/clusters/${resolvedCluster}/k8s/apis/${resolvedApiGroup}/${resolvedApiVersion}/${resolvedPlural}`,
81784
+ {
81785
+ params: {
81786
+ fieldSelector: `metadata.name=${resolvedResourceName}`
81787
+ }
81788
+ }
81789
+ );
81790
+ const spec = data?.items?.[0]?.spec;
81791
+ return spec?.pathToNavigateFromClusterList;
81792
+ } catch {
81793
+ return void 0;
81794
+ }
81795
+ };
81796
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
81797
+ TableComponents.TableContainer,
81798
+ {
81799
+ $isDark: theme === "dark",
81800
+ $isCursorPointer: !!recordKeysForNavigation && (!!pathToNavigate || !!navigationSettings),
81801
+ $borderless: tableProps?.borderless,
81802
+ $isTotalLeft: tableProps?.isTotalLeft,
81803
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(TableComponents.HideableControls, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(
81804
+ Table,
81805
+ {
81806
+ rowKey,
81807
+ dataSource,
81808
+ columns: enrichedColumns,
81809
+ pagination: tableProps?.disablePagination ? false : {
81810
+ position: tableProps?.paginationPosition || ["bottomLeft"],
81811
+ showSizeChanger: true,
81812
+ defaultPageSize: 10,
81813
+ hideOnSinglePage: false,
81814
+ showTotal
81815
+ },
81816
+ scroll: { x: "max-content", y: tableProps?.maxHeight },
81817
+ virtual: tableProps?.virtual,
81818
+ onRow: (record) => {
81819
+ return {
81820
+ onClick: async () => {
81821
+ if (recordKeysForNavigation) {
81822
+ const recordValueRaw = Array.isArray(recordKeysForNavigation) ? lodashExports.get(record, recordKeysForNavigation) : jp.query(record || {}, `$${recordKeysForNavigation}`)[0];
81823
+ const clusterName = typeof recordValueRaw === "string" ? recordValueRaw : void 0;
81824
+ const recordValue = typeof recordValueRaw === "string" ? recordValueRaw : JSON.stringify(recordValueRaw);
81825
+ const fetchedPathToNavigate = await tryGetPathFromNavigationResource(clusterName);
81826
+ const finalPathToNavigate = fetchedPathToNavigate || pathToNavigate;
81827
+ if (!finalPathToNavigate) {
81828
+ return;
81829
+ }
81830
+ const newPath = finalPathToNavigate.replaceAll("~recordValue~", recordValue);
81831
+ navigate(newPath);
81832
+ }
81833
+ }
81834
+ };
81835
+ }
81836
+ }
81837
+ ) })
81838
+ }
81839
+ );
81840
+ };
81841
+
81310
81842
  const prepare = ({
81311
81843
  dataItems,
81312
81844
  pathToKey,
@@ -82528,15 +83060,16 @@ const FormListInput = ({
82528
83060
  /* @__PURE__ */ jsxRuntimeExports.jsx(PersistedCheckbox, { formName: persistName || name, persistedControls, type: "arr" })
82529
83061
  ] })
82530
83062
  ] }),
82531
- /* @__PURE__ */ jsxRuntimeExports.jsx(
82532
- ResetedFormItem$1,
82533
- {
82534
- name: arrName || fixedName,
82535
- rules: [getRequiredRule(forceNonRequired === false && !!required?.includes(getStringByName(name)), name)],
82536
- validateTrigger: "onBlur",
82537
- hasFeedback: designNewLayout ? { icons: feedbackIcons } : true,
82538
- children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Flex, { gap: 8, align: "center", children: [
82539
- /* @__PURE__ */ jsxRuntimeExports.jsx(
83063
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(Flex, { gap: 8, align: "center", children: [
83064
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
83065
+ ResetedFormItem$1,
83066
+ {
83067
+ name: arrName || fixedName,
83068
+ rules: [getRequiredRule(forceNonRequired === false && !!required?.includes(getStringByName(name)), name)],
83069
+ validateTrigger: "onBlur",
83070
+ hasFeedback: designNewLayout ? { icons: feedbackIcons } : true,
83071
+ style: { flex: 1 },
83072
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(
82540
83073
  Select,
82541
83074
  {
82542
83075
  mode: customProps.mode,
@@ -82548,12 +83081,12 @@ const FormListInput = ({
82548
83081
  showSearch: true,
82549
83082
  style: { width: "100%" }
82550
83083
  }
82551
- ),
82552
- relatedValueTooltip && /* @__PURE__ */ jsxRuntimeExports.jsx(Tooltip$1, { title: relatedValueTooltip, children: /* @__PURE__ */ jsxRuntimeExports.jsx(QuestionCircleOutlined, {}) })
82553
- ] })
82554
- },
82555
- arrKey !== void 0 ? arrKey : Array.isArray(name) ? name.slice(-1)[0] : name
82556
- )
83084
+ )
83085
+ },
83086
+ arrKey !== void 0 ? arrKey : Array.isArray(name) ? name.slice(-1)[0] : name
83087
+ ),
83088
+ relatedValueTooltip && /* @__PURE__ */ jsxRuntimeExports.jsx(Tooltip$1, { title: relatedValueTooltip, children: /* @__PURE__ */ jsxRuntimeExports.jsx(QuestionCircleOutlined, {}) })
83089
+ ] })
82557
83090
  ] });
82558
83091
  };
82559
83092
 
@@ -90130,5 +90663,5 @@ const usePluginManifest = ({
90130
90663
  });
90131
90664
  };
90132
90665
 
90133
- export { useInfiniteSentinel as $, getBuiltinResourceTypes as A, getCrdData as B, getDirectUnknownResource as C, DeleteIcon as D, EnrichedTableProvider as E, checkPermission as F, getSwagger as G, filterIfApiInstanceNamespaceScoped as H, filterIfBuiltInInstanceNamespaceScoped as I, checkIfApiInstanceNamespaceScoped as J, checkIfBuiltInInstanceNamespaceScoped as K, getKinds as L, useClusterList as M, useApiResources as N, useApiResourceSingle as O, PaddingContainer as P, useBuiltinResources as Q, ReadOnlyModal as R, useBuiltinResourceSingle as S, useCrdResources as T, useCrdResourceSingle as U, useApisResourceTypes as V, useApiResourceTypesByGroup as W, useBuiltinResourceTypes as X, useCrdData as Y, useListWatch as Z, _$1 as _, useTheme as a, parseQuotaValueMemoryAndStorage as a$, useK8sVerbs as a0, useManyK8sSmartResource as a1, useSmartResourceParams as a2, useResourceScope as a3, useKinds as a4, usePluginManifest as a5, Spacer$1 as a6, TreeWithSearch as a7, ConfirmModal as a8, UpIcon as a9, EnrichedTable as aA, getEnrichedColumns as aB, getEnrichedColumnsWithControls as aC, YamlEditorSingleton$1 as aD, BlackholeFormProvider as aE, BlackholeForm as aF, getObjectFormItemsDraft as aG, MarketPlace as aH, MarketplaceCard as aI, ProjectInfoCard as aJ, PodTerminal as aK, NodeTerminal as aL, PodLogs as aM, PodLogsMonaco as aN, VMVNC as aO, Search as aP, Events as aQ, DynamicRenderer as aR, DynamicComponents as aS, DynamicRendererWithProviders as aT, prepareTemplate as aU, isFlatObject as aV, filterSelectOptions as aW, getStringByName as aX, floorToDecimal as aY, parseQuotaValue as aZ, parseQuotaValueCpu as a_, DownIcon as aa, BackToDefaultIcon as ab, SuccessIcon as ac, feedbackIcons as ad, PlusIcon as ae, MinusIcon as af, LockedIcon as ag, UnlockedIcon as ah, PauseCircleIcon as ai, ResumeCircleIcon as aj, LookingGlassIcon as ak, EarthIcon as al, ContentCard$1 as am, FlexGrow as an, UncontrolledSelect as ao, CustomSelect$4 as ap, CursorPointerTag as aq, CursorPointerTagMinContent as ar, CursorDefaultDiv as as, ResourceLink as at, ManageableBreadcrumbsProvider as au, prepareDataForManageableBreadcrumbs as av, ManageableBreadcrumbs as aw, ManageableSidebarProvider as ax, prepareDataForManageableSidebar as ay, ManageableSidebar as az, usePartsOfUrl as b, normalizeValuesForQuotasToNumber as b0, getAllPathsFromObj as b1, getPrefixSubarrays as b2, groupsToTreeData as b3, getBuiltinTreeData as b4, getGroupsByCategory as b5, createContextFactory as b6, prepareUrlsToFetchForDynamicRenderer as b7, deepMerge as b8, getSortedKinds as b9, getSortedKindsAll as ba, hslFromString as bb, getUppercase as bc, kindByGvr as bd, pluralByKind as be, namespacedByGvr as bf, getLinkToBuiltinForm as bg, getLinkToApiForm as bh, isMultilineString as bi, isMultilineFromYaml as bj, includesArray as bk, getResourceLink as bl, getNamespaceLink as bm, convertBytes as bn, formatBytesAuto as bo, toBytes as bp, convertStorage as bq, parseValueWithUnit as br, convertCores as bs, formatCoresAuto as bt, toCores as bu, convertCompute as bv, parseCoresWithUnit as bw, formatDateAuto as bx, isValidRFC3339 as by, usePermissions as c, useDirectUnknownResource as d, useK8sSmartResource as e, jsxRuntimeExports as f, EditIcon as g, getLinkToForm as h, DeleteModal as i, jp as j, DeleteModalMany as k, getClusterList as l, createNewEntry as m, updateEntry as n, deleteEntry as o, parseAll as p, getApiResources as q, getApiResourceSingle as r, serializeLabelsWithNoEncoding$1 as s, getBuiltinResources as t, useMultiQuery as u, getBuiltinResourceSingle as v, getCrdResources as w, getCrdResourceSingle as x, getApiResourceTypes as y, getApiResourceTypesByApiGroup as z };
90134
- //# sourceMappingURL=index-CWMOa8gQ.mjs.map
90666
+ export { useInfiniteSentinel as $, getBuiltinResourceTypes as A, getCrdData as B, getDirectUnknownResource as C, DeleteIcon as D, EnrichedTableProvider as E, checkPermission as F, getSwagger as G, filterIfApiInstanceNamespaceScoped as H, filterIfBuiltInInstanceNamespaceScoped as I, checkIfApiInstanceNamespaceScoped as J, checkIfBuiltInInstanceNamespaceScoped as K, getKinds as L, useClusterList as M, useApiResources as N, useApiResourceSingle as O, PaddingContainer as P, useBuiltinResources as Q, ReadOnlyModal as R, useBuiltinResourceSingle as S, useCrdResources as T, useCrdResourceSingle as U, useApisResourceTypes as V, useApiResourceTypesByGroup as W, useBuiltinResourceTypes as X, useCrdData as Y, useListWatch as Z, _$1 as _, useTheme as a, parseQuotaValueCpu as a$, useK8sVerbs as a0, useManyK8sSmartResource as a1, useSmartResourceParams as a2, useResourceScope as a3, useKinds as a4, usePluginManifest as a5, Spacer$1 as a6, TreeWithSearch as a7, ConfirmModal as a8, UpIcon as a9, EnrichedTable as aA, ClusterListTable as aB, getEnrichedColumns as aC, getEnrichedColumnsWithControls as aD, YamlEditorSingleton$1 as aE, BlackholeFormProvider as aF, BlackholeForm as aG, getObjectFormItemsDraft as aH, MarketPlace as aI, MarketplaceCard as aJ, ProjectInfoCard as aK, PodTerminal as aL, NodeTerminal as aM, PodLogs as aN, PodLogsMonaco as aO, VMVNC as aP, Search as aQ, Events as aR, DynamicRenderer as aS, DynamicComponents as aT, DynamicRendererWithProviders as aU, prepareTemplate as aV, isFlatObject as aW, filterSelectOptions as aX, getStringByName as aY, floorToDecimal as aZ, parseQuotaValue as a_, DownIcon as aa, BackToDefaultIcon as ab, SuccessIcon as ac, feedbackIcons as ad, PlusIcon as ae, MinusIcon as af, LockedIcon as ag, UnlockedIcon as ah, PauseCircleIcon as ai, ResumeCircleIcon as aj, LookingGlassIcon as ak, EarthIcon as al, ContentCard$1 as am, FlexGrow as an, UncontrolledSelect as ao, CustomSelect$4 as ap, CursorPointerTag as aq, CursorPointerTagMinContent as ar, CursorDefaultDiv as as, ResourceLink as at, ManageableBreadcrumbsProvider as au, prepareDataForManageableBreadcrumbs as av, ManageableBreadcrumbs as aw, ManageableSidebarProvider as ax, prepareDataForManageableSidebar as ay, ManageableSidebar as az, usePartsOfUrl as b, parseQuotaValueMemoryAndStorage as b0, normalizeValuesForQuotasToNumber as b1, getAllPathsFromObj as b2, getPrefixSubarrays as b3, groupsToTreeData as b4, getBuiltinTreeData as b5, getGroupsByCategory as b6, createContextFactory as b7, prepareUrlsToFetchForDynamicRenderer as b8, deepMerge as b9, getSortedKinds as ba, getSortedKindsAll as bb, hslFromString as bc, getUppercase as bd, kindByGvr as be, pluralByKind as bf, namespacedByGvr as bg, getLinkToBuiltinForm as bh, getLinkToApiForm as bi, isMultilineString as bj, isMultilineFromYaml as bk, includesArray as bl, getResourceLink as bm, getNamespaceLink as bn, convertBytes as bo, formatBytesAuto as bp, toBytes as bq, convertStorage as br, parseValueWithUnit as bs, convertCores as bt, formatCoresAuto as bu, toCores as bv, convertCompute as bw, parseCoresWithUnit as bx, formatDateAuto as by, isValidRFC3339 as bz, usePermissions as c, useDirectUnknownResource as d, useK8sSmartResource as e, jsxRuntimeExports as f, EditIcon as g, getLinkToForm as h, DeleteModal as i, jp as j, DeleteModalMany as k, getClusterList as l, createNewEntry as m, updateEntry as n, deleteEntry as o, parseAll as p, getApiResources as q, getApiResourceSingle as r, serializeLabelsWithNoEncoding$1 as s, getBuiltinResources as t, useMultiQuery as u, getBuiltinResourceSingle as v, getCrdResources as w, getCrdResourceSingle as x, getApiResourceTypes as y, getApiResourceTypesByApiGroup as z };
90667
+ //# sourceMappingURL=index-DuYZpKMC.mjs.map