@prorobotech/openapi-k8s-toolkit 1.4.0-alpha.8 → 1.4.0-alpha.9

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 (23) hide show
  1. package/dist/{index-DPPcb4Gw.mjs → index-85og70S2.mjs} +2 -2
  2. package/dist/{index-DPPcb4Gw.mjs.map → index-85og70S2.mjs.map} +1 -1
  3. package/dist/{index-DGEm7Wqt.mjs → index-BwCZPalv.mjs} +781 -229
  4. package/dist/index-BwCZPalv.mjs.map +1 -0
  5. package/dist/openapi-k8s-toolkit.es.js +1 -1
  6. package/dist/openapi-k8s-toolkit.umd.js +777 -225
  7. package/dist/openapi-k8s-toolkit.umd.js.map +1 -1
  8. package/dist/types/components/molecules/YamlEditorSingleton/utils.d.ts +3 -0
  9. package/dist/types/components/molecules/YamlEditorSingleton/utils.test.d.ts +1 -0
  10. package/dist/types/components/organisms/DynamicComponents/molecules/ActionsDropdown/hooks/useActionsDropdownHandlers.d.ts +34 -2
  11. package/dist/types/components/organisms/DynamicComponents/molecules/ActionsDropdown/hooks/useActionsDropdownPermissions.d.ts +2 -3
  12. package/dist/types/components/organisms/DynamicComponents/molecules/ActionsDropdown/modals/ScaleModal.d.ts +10 -0
  13. package/dist/types/components/organisms/DynamicComponents/molecules/ActionsDropdown/permissionsMap.d.ts +7 -0
  14. package/dist/types/components/organisms/DynamicComponents/molecules/ActionsDropdown/utils.d.ts +9 -7
  15. package/dist/types/components/organisms/DynamicComponents/molecules/LabelsToSearchParams/utils.d.ts +6 -0
  16. package/dist/types/components/organisms/DynamicComponents/molecules/SecretBase64Plain/styled.d.ts +1 -0
  17. package/dist/types/components/organisms/DynamicComponents/molecules/SecretBase64Plain/utils.d.ts +2 -0
  18. package/dist/types/components/organisms/DynamicComponents/molecules/SecretBase64Plain/utils.test.d.ts +1 -0
  19. package/dist/types/components/organisms/DynamicComponents/types/ActionsDropdown.d.ts +59 -17
  20. package/dist/types/components/organisms/DynamicComponents/types/LabelsToSearchParams.d.ts +1 -0
  21. package/dist/types/components/organisms/DynamicComponents/types/SecretBase64Plain.d.ts +10 -0
  22. package/package.json +5 -5
  23. package/dist/index-DGEm7Wqt.mjs.map +0 -1
@@ -2164,7 +2164,7 @@
2164
2164
  *
2165
2165
  * @returns {?Array}
2166
2166
  */
2167
- const toArray$4 = (thing) => {
2167
+ const toArray$3 = (thing) => {
2168
2168
  if (!thing) return null;
2169
2169
  if (isArray(thing)) return thing;
2170
2170
  let i = thing.length;
@@ -2444,7 +2444,7 @@
2444
2444
  kindOf: kindOf$1,
2445
2445
  kindOfTest,
2446
2446
  endsWith,
2447
- toArray: toArray$4,
2447
+ toArray: toArray$3,
2448
2448
  forEachEntry,
2449
2449
  matchAll,
2450
2450
  isHTMLForm,
@@ -43439,6 +43439,36 @@
43439
43439
  BigText: BigText$1
43440
43440
  };
43441
43441
 
43442
+ const findManagedFieldsLine = (model) => {
43443
+ let inMetadata = false;
43444
+ let metadataIndent = -1;
43445
+ for (let lineNumber = 1; lineNumber <= model.getLineCount(); lineNumber++) {
43446
+ const line = model.getLineContent(lineNumber);
43447
+ const trimmed = line.trim();
43448
+ const indent = line.match(/^\s*/)?.[0].length ?? 0;
43449
+ if (!inMetadata && /^metadata\s*:\s*$/.test(trimmed)) {
43450
+ inMetadata = true;
43451
+ metadataIndent = indent;
43452
+ } else if (inMetadata) {
43453
+ if (trimmed && indent <= metadataIndent) {
43454
+ inMetadata = false;
43455
+ } else if (/^managedFields\s*:\s*$/.test(trimmed)) {
43456
+ return lineNumber;
43457
+ }
43458
+ }
43459
+ }
43460
+ return null;
43461
+ };
43462
+ const collapseManagedFieldsInEditor = (editor) => {
43463
+ const model = editor.getModel();
43464
+ if (!model) return;
43465
+ const managedFieldsLine = findManagedFieldsLine(model);
43466
+ if (managedFieldsLine === null) return;
43467
+ if (managedFieldsLine >= model.getLineCount()) return;
43468
+ editor.setPosition({ lineNumber: managedFieldsLine, column: 1 });
43469
+ editor.trigger("managed-fields-collapse", "editor.fold", null);
43470
+ };
43471
+
43442
43472
  const NOTIFICATION_KEY = "yaml-data-changed";
43443
43473
  const YamlEditorSingleton$1 = ({
43444
43474
  theme,
@@ -43465,6 +43495,12 @@
43465
43495
  const initialPrefillYamlRef = React$1.useRef(null);
43466
43496
  const latestPrefillYamlRef = React$1.useRef(null);
43467
43497
  const firstLoadRef = React$1.useRef(true);
43498
+ const editorRef = React$1.useRef(null);
43499
+ const collapseManagedFieldsIfNeeded = React$1.useCallback(() => {
43500
+ const editor = editorRef.current;
43501
+ if (!editor) return;
43502
+ collapseManagedFieldsInEditor(editor);
43503
+ }, []);
43468
43504
  const handleReload = React$1.useCallback(() => {
43469
43505
  api.destroy(NOTIFICATION_KEY);
43470
43506
  const nextYaml = latestPrefillYamlRef.current ?? initialPrefillYamlRef.current;
@@ -43508,6 +43544,12 @@
43508
43544
  }
43509
43545
  latestPrefillYamlRef.current = nextYaml;
43510
43546
  }, [prefillValuesSchema, openNotificationYamlChanged]);
43547
+ React$1.useEffect(() => {
43548
+ const id = setTimeout(() => {
43549
+ collapseManagedFieldsIfNeeded();
43550
+ }, 0);
43551
+ return () => clearTimeout(id);
43552
+ }, [yamlData, collapseManagedFieldsIfNeeded]);
43511
43553
  const onSubmit = () => {
43512
43554
  setIsLoading(true);
43513
43555
  setError(void 0);
@@ -43565,6 +43607,12 @@
43565
43607
  width: "100%",
43566
43608
  height: designNewLayoutHeight || "75vh",
43567
43609
  value: yamlData,
43610
+ onMount: (editor) => {
43611
+ editorRef.current = editor;
43612
+ setTimeout(() => {
43613
+ collapseManagedFieldsIfNeeded();
43614
+ }, 0);
43615
+ },
43568
43616
  onChange: (value) => {
43569
43617
  if (!readOnly) {
43570
43618
  setYamlData(value || "");
@@ -44140,15 +44188,15 @@
44140
44188
  };
44141
44189
 
44142
44190
  const includesPath = (haystack, needle) => haystack.some((h) => h.length === needle.length && h.every((seg, i) => seg === String(needle[i])));
44143
- const toArray$3 = (p) => (
44191
+ const toArray$2 = (p) => (
44144
44192
  // eslint-disable-next-line no-nested-ternary
44145
44193
  p === void 0 ? void 0 : Array.isArray(p) ? p : [p]
44146
44194
  );
44147
44195
 
44148
44196
  const HiddenContainer$1 = ({ name, secondName, children }) => {
44149
44197
  const hiddenPaths = useHiddenPathsLayout();
44150
- const nameArr = toArray$3(name);
44151
- const secondArr = toArray$3(secondName);
44198
+ const nameArr = toArray$2(name);
44199
+ const secondArr = toArray$2(secondName);
44152
44200
  const isHidden = !!hiddenPaths && !!nameArr && includesPath(hiddenPaths, nameArr);
44153
44201
  const isHiddenSecond = !!hiddenPaths && !!secondArr && includesPath(hiddenPaths, secondArr);
44154
44202
  return /* @__PURE__ */ jsxRuntimeExports.jsx(PossibleHiddenContainer, { $isHidden: !hiddenPaths || isHidden || isHiddenSecond, children });
@@ -45101,7 +45149,24 @@
45101
45149
  ] });
45102
45150
  };
45103
45151
 
45152
+ const handleLabelsToSearchParamsLinkClick = ({
45153
+ e,
45154
+ hrefPrepared,
45155
+ navigate
45156
+ }) => {
45157
+ const isExternal = isExternalHref(hrefPrepared);
45158
+ if (isExternal) {
45159
+ return;
45160
+ }
45161
+ e.preventDefault();
45162
+ navigate(hrefPrepared);
45163
+ };
45164
+
45104
45165
  const LabelsToSearchParams = ({ data, children }) => {
45166
+ const renderWithSearchIcon = (content) => /* @__PURE__ */ jsxRuntimeExports.jsxs(antd.Flex, { align: "flex-start", gap: 8, children: [
45167
+ /* @__PURE__ */ jsxRuntimeExports.jsx(AntIcons.SearchOutlined, { style: { marginTop: 4 } }),
45168
+ content
45169
+ ] });
45105
45170
  const {
45106
45171
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
45107
45172
  id,
@@ -45110,10 +45175,12 @@
45110
45175
  linkPrefix,
45111
45176
  textLink,
45112
45177
  errorText,
45178
+ errorMode = "errorText",
45113
45179
  maxTextLength,
45114
45180
  renderLabelsAsRows,
45115
45181
  ...linkProps
45116
45182
  } = data;
45183
+ const navigate = reactRouterDom.useNavigate();
45117
45184
  const { data: multiQueryData, isLoading: isMultiQueryLoading, isError: isMultiQueryErrors, errors } = useMultiQuery();
45118
45185
  const partsOfUrl = usePartsOfUrl();
45119
45186
  if (isMultiQueryLoading) {
@@ -45136,32 +45203,53 @@
45136
45203
  const anythingForNow = jp.query(jsonRoot || {}, `$${jsonPathToLabels}`);
45137
45204
  const { data: labelsRaw, error: errorArrayOfObjects } = parseLabelsArrayOfAny(anythingForNow);
45138
45205
  const linkPrefixPrepared = parseAll({ text: linkPrefix, replaceValues, multiQueryData });
45206
+ const labelsPrefixPrepared = linkPrefixPrepared.includes("?") ? `${linkPrefixPrepared}${linkPrefixPrepared.endsWith("?") || linkPrefixPrepared.endsWith("&") ? "" : "&"}labels=` : `${linkPrefixPrepared}?labels=`;
45207
+ const renderErrorFallback = () => {
45208
+ if (errorMode === "default") {
45209
+ const fallbackText = textLink || errorText;
45210
+ const handleDefaultFallbackLinkClick = (e) => handleLabelsToSearchParamsLinkClick({
45211
+ e,
45212
+ hrefPrepared: linkPrefixPrepared,
45213
+ navigate
45214
+ });
45215
+ return renderWithSearchIcon(
45216
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(antd.Typography.Link, { href: linkPrefixPrepared, onClick: handleDefaultFallbackLinkClick, ...linkProps, children: [
45217
+ fallbackText,
45218
+ children
45219
+ ] })
45220
+ );
45221
+ }
45222
+ return renderWithSearchIcon(
45223
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(antd.Typography.Text, { children: [
45224
+ errorText,
45225
+ children
45226
+ ] })
45227
+ );
45228
+ };
45139
45229
  if (!labelsRaw) {
45140
45230
  if (errorArrayOfObjects) {
45141
45231
  console.log(errorArrayOfObjects);
45142
- return /* @__PURE__ */ jsxRuntimeExports.jsxs(antd.Typography.Text, { children: [
45143
- errorText,
45144
- children
45145
- ] });
45232
+ return renderErrorFallback();
45146
45233
  }
45147
45234
  console.log("Not a valid data structure");
45148
- return /* @__PURE__ */ jsxRuntimeExports.jsxs(antd.Typography.Text, { children: [
45149
- errorText,
45150
- children
45151
- ] });
45235
+ return renderErrorFallback();
45152
45236
  }
45153
45237
  const labels = Object.entries(labelsRaw).map(([key, value]) => `${key}=${value}`).join(",");
45154
45238
  const labelsRows = Object.entries(labelsRaw).map(([key, value]) => `${key}=${value}`);
45155
45239
  const labelsEncoded = encodeURIComponent(labels);
45156
- const hrefPrepared = `${linkPrefixPrepared}${labelsEncoded}`;
45240
+ const hrefPrepared = `${labelsPrefixPrepared}${labelsEncoded}`;
45241
+ const handleLinkClick = (e) => handleLabelsToSearchParamsLinkClick({
45242
+ e,
45243
+ hrefPrepared,
45244
+ navigate
45245
+ });
45157
45246
  if (renderLabelsAsRows) {
45158
- return /* @__PURE__ */ jsxRuntimeExports.jsxs(antd.Flex, { align: "flex-start", gap: 8, children: [
45159
- /* @__PURE__ */ jsxRuntimeExports.jsx(AntIcons.SearchOutlined, { style: { marginTop: 4 } }),
45247
+ return renderWithSearchIcon(
45160
45248
  /* @__PURE__ */ jsxRuntimeExports.jsxs(antd.Flex, { vertical: true, children: [
45161
- labelsRows.map((row, index) => /* @__PURE__ */ jsxRuntimeExports.jsx(antd.Typography.Link, { href: hrefPrepared, ...linkProps, children: index < labelsRows.length - 1 ? `${row},` : row }, row)),
45249
+ /* @__PURE__ */ jsxRuntimeExports.jsx(antd.Typography.Link, { href: hrefPrepared, onClick: handleLinkClick, ...linkProps, children: labelsRows.map((row, index) => /* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { display: "block" }, children: index < labelsRows.length - 1 ? `${row},` : row }, `${row}-${index}`)) }),
45162
45250
  children
45163
45251
  ] })
45164
- ] });
45252
+ );
45165
45253
  }
45166
45254
  if (maxTextLength && !textLink) {
45167
45255
  const truncatedLabels = maxTextLength ? truncate$1(labels, maxTextLength) : labels;
@@ -45169,10 +45257,12 @@
45169
45257
  antd.Popover,
45170
45258
  {
45171
45259
  content: /* @__PURE__ */ jsxRuntimeExports.jsx(antd.Flex, { vertical: true, gap: 8, children: Object.entries(labelsRaw).map(([key, value]) => /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: `${key}=${value}` }, key)) }),
45172
- children: /* @__PURE__ */ jsxRuntimeExports.jsxs(antd.Typography.Link, { href: hrefPrepared, ...linkProps, children: [
45173
- truncatedLabels,
45174
- children
45175
- ] })
45260
+ children: renderWithSearchIcon(
45261
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(antd.Typography.Link, { href: hrefPrepared, onClick: handleLinkClick, ...linkProps, children: [
45262
+ truncatedLabels,
45263
+ children
45264
+ ] })
45265
+ )
45176
45266
  }
45177
45267
  );
45178
45268
  }
@@ -45182,17 +45272,21 @@
45182
45272
  antd.Popover,
45183
45273
  {
45184
45274
  content: /* @__PURE__ */ jsxRuntimeExports.jsx(antd.Flex, { vertical: true, gap: 8, children: Object.entries(labelsRaw).map(([key, value]) => /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: `${key}=${value}` }, key)) }),
45185
- children: /* @__PURE__ */ jsxRuntimeExports.jsxs(antd.Typography.Link, { href: hrefPrepared, ...linkProps, children: [
45186
- truncatedTextLink,
45187
- children
45188
- ] })
45275
+ children: renderWithSearchIcon(
45276
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(antd.Typography.Link, { href: hrefPrepared, onClick: handleLinkClick, ...linkProps, children: [
45277
+ truncatedTextLink,
45278
+ children
45279
+ ] })
45280
+ )
45189
45281
  }
45190
45282
  );
45191
45283
  }
45192
- return /* @__PURE__ */ jsxRuntimeExports.jsxs(antd.Typography.Link, { href: hrefPrepared, ...linkProps, children: [
45193
- textLink || labels,
45194
- children
45195
- ] });
45284
+ return renderWithSearchIcon(
45285
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(antd.Typography.Link, { href: hrefPrepared, onClick: handleLinkClick, ...linkProps, children: [
45286
+ textLink || labels,
45287
+ children
45288
+ ] })
45289
+ );
45196
45290
  };
45197
45291
 
45198
45292
  const flattenOnce$1 = (arr) => arr.reduce((acc, row) => [...acc, ...row], []);
@@ -46766,9 +46860,15 @@ if (_IS_WORKLET) registerPaint("spoiler", SpoilerPainterWorklet);
46766
46860
  user-select: none;
46767
46861
  }
46768
46862
  `;
46769
- const DisabledInput = styled(antd.Input)`
46863
+ const hiddenCursor = styled.css`
46770
46864
  /* stylelint-disable declaration-no-important */
46771
46865
  cursor: ${({ $hidden }) => $hidden ? "default" : "pointer"} !important;
46866
+ `;
46867
+ const DisabledInput = styled(antd.Input)`
46868
+ ${hiddenCursor}
46869
+ `;
46870
+ const DisabledTextArea = styled(antd.Input.TextArea)`
46871
+ ${hiddenCursor}
46772
46872
  `;
46773
46873
  const NotificationOverrides = styled.createGlobalStyle`
46774
46874
  .no-message-notif .ant-notification-notice-message {
@@ -46778,15 +46878,45 @@ if (_IS_WORKLET) registerPaint("spoiler", SpoilerPainterWorklet);
46778
46878
  const Styled$s = {
46779
46879
  NoSelect,
46780
46880
  DisabledInput,
46881
+ DisabledTextArea,
46781
46882
  NotificationOverrides
46782
46883
  };
46783
46884
 
46885
+ const decodeIfBase64 = (value, shouldDecode) => {
46886
+ if (!shouldDecode) {
46887
+ return value;
46888
+ }
46889
+ try {
46890
+ return atob(value);
46891
+ } catch (error) {
46892
+ console.error(error);
46893
+ return value;
46894
+ }
46895
+ };
46896
+ const resolveMultilineRows = (value, multilineRows) => {
46897
+ const computedRows = Math.min(12, Math.max(3, value.split(/\r\n|\r|\n/).length));
46898
+ if (typeof multilineRows === "number" && Number.isFinite(multilineRows)) {
46899
+ return Math.min(30, Math.max(1, Math.floor(multilineRows)));
46900
+ }
46901
+ return computedRows;
46902
+ };
46903
+
46784
46904
  const SecretBase64Plain = ({ data }) => {
46785
46905
  const {
46786
46906
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
46787
46907
  id,
46908
+ type,
46909
+ value,
46910
+ reqIndex,
46911
+ jsonPathToSecrets,
46788
46912
  base64Value,
46789
46913
  plainTextValue,
46914
+ multiline,
46915
+ multilineRows,
46916
+ shownByDefault,
46917
+ hideEye,
46918
+ textStyle,
46919
+ emptyText,
46790
46920
  containerStyle,
46791
46921
  inputContainerStyle,
46792
46922
  flexProps,
@@ -46794,8 +46924,9 @@ if (_IS_WORKLET) registerPaint("spoiler", SpoilerPainterWorklet);
46794
46924
  notificationText,
46795
46925
  notificationWidth
46796
46926
  } = data;
46797
- const [hidden, setHidden] = React$1.useState(true);
46798
- const inputRef = React$1.useRef(null);
46927
+ const hiddenDefault = !shownByDefault;
46928
+ const [hidden, setHidden] = React$1.useState(hiddenDefault);
46929
+ const [hiddenByKey, setHiddenByKey] = React$1.useState({});
46799
46930
  const [notificationApi, contextHolder] = antd.notification.useNotification();
46800
46931
  const { data: multiQueryData, isLoading, isError, errors } = useMultiQuery();
46801
46932
  const partsOfUrl = usePartsOfUrl();
@@ -46809,20 +46940,26 @@ if (_IS_WORKLET) registerPaint("spoiler", SpoilerPainterWorklet);
46809
46940
  /* @__PURE__ */ jsxRuntimeExports.jsx("ul", { children: errors.map((e, i) => e && /* @__PURE__ */ jsxRuntimeExports.jsx("li", { children: typeof e === "string" ? e : e.message }, i)) })
46810
46941
  ] });
46811
46942
  }
46812
- const replaceValues = partsOfUrl.partsOfUrl.reduce((acc, value, index) => {
46813
- acc[index.toString()] = value;
46943
+ const replaceValues = partsOfUrl.partsOfUrl.reduce((acc, value2, index) => {
46944
+ acc[index.toString()] = value2;
46814
46945
  return acc;
46815
46946
  }, {});
46816
46947
  const parsedText = parseAll({
46817
- text: base64Value || plainTextValue || "Oneof required",
46948
+ text: value ?? base64Value ?? plainTextValue ?? "Value required",
46818
46949
  replaceValues,
46819
46950
  multiQueryData
46820
46951
  });
46821
- const decodedText = base64Value ? atob(parsedText) : parsedText;
46822
- const copyToClipboard = async () => {
46952
+ const emptyTextPrepared = typeof emptyText === "string" && emptyText.length > 0 ? parseAll({
46953
+ text: emptyText,
46954
+ replaceValues,
46955
+ multiQueryData
46956
+ }) : void 0;
46957
+ const shouldDecodeSingle = type === "base64" ? true : type === "plain" ? false : base64Value !== void 0;
46958
+ const decodedText = decodeIfBase64(parsedText, shouldDecodeSingle);
46959
+ const copyToClipboard = async (valueToCopy) => {
46823
46960
  try {
46824
- if (decodedText !== null && decodedText !== void 0) {
46825
- await navigator.clipboard.writeText(decodedText);
46961
+ if (valueToCopy !== null && valueToCopy !== void 0) {
46962
+ await navigator.clipboard.writeText(valueToCopy);
46826
46963
  notificationApi.info({
46827
46964
  // message: `Copied: ${decodedText.substring(0, 5)}...`,
46828
46965
  message: notificationText || "Text copied to clipboard",
@@ -46840,42 +46977,103 @@ if (_IS_WORKLET) registerPaint("spoiler", SpoilerPainterWorklet);
46840
46977
  console.error(error);
46841
46978
  }
46842
46979
  };
46843
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: containerStyle, children: [
46844
- /* @__PURE__ */ jsxRuntimeExports.jsx(Styled$s.NotificationOverrides, {}),
46845
- /* @__PURE__ */ jsxRuntimeExports.jsxs(antd.Flex, { gap: 8, ...flexProps, children: [
46846
- /* @__PURE__ */ jsxRuntimeExports.jsx(Styled$s.NoSelect, { style: inputContainerStyle, children: niceLooking ? /* @__PURE__ */ jsxRuntimeExports.jsx(te, { theme, hidden, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
46980
+ const handleInputClick = async (e, isHidden, valueToCopy) => {
46981
+ if (isHidden) {
46982
+ return;
46983
+ }
46984
+ e.currentTarget.focus();
46985
+ e.currentTarget.select();
46986
+ await copyToClipboard(valueToCopy);
46987
+ };
46988
+ const useNiceLooking = !!niceLooking && !multiline;
46989
+ const renderSecretField = ({
46990
+ value: value2,
46991
+ isHidden,
46992
+ onToggle
46993
+ }) => {
46994
+ const effectiveHidden = hideEye ? false : isHidden;
46995
+ const shownValue = useNiceLooking ? value2 : effectiveHidden ? "" : value2;
46996
+ const resolvedMultilineRows = resolveMultilineRows(value2, multilineRows);
46997
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(antd.Flex, { gap: 8, ...flexProps, children: [
46998
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Styled$s.NoSelect, { style: inputContainerStyle, children: useNiceLooking ? /* @__PURE__ */ jsxRuntimeExports.jsx(te, { theme, hidden: effectiveHidden, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
46847
46999
  Styled$s.DisabledInput,
46848
47000
  {
46849
- $hidden: hidden,
46850
- ref: inputRef,
46851
- onClick: () => {
46852
- if (!hidden) {
46853
- inputRef.current?.focus({
46854
- cursor: "all"
46855
- });
46856
- copyToClipboard();
46857
- }
46858
- },
46859
- value: decodedText
47001
+ $hidden: effectiveHidden,
47002
+ onClick: (e) => handleInputClick(e, effectiveHidden, value2),
47003
+ value: shownValue,
47004
+ readOnly: true
46860
47005
  }
46861
- ) }) : /* @__PURE__ */ jsxRuntimeExports.jsx(
47006
+ ) }) : multiline ? /* @__PURE__ */ jsxRuntimeExports.jsx(
47007
+ Styled$s.DisabledTextArea,
47008
+ {
47009
+ $hidden: effectiveHidden,
47010
+ onClick: (e) => handleInputClick(e, effectiveHidden, value2),
47011
+ value: shownValue,
47012
+ rows: resolvedMultilineRows,
47013
+ readOnly: true
47014
+ }
47015
+ ) : /* @__PURE__ */ jsxRuntimeExports.jsx(
46862
47016
  Styled$s.DisabledInput,
46863
47017
  {
46864
- $hidden: hidden,
46865
- ref: inputRef,
46866
- onClick: () => {
46867
- if (!hidden) {
46868
- inputRef.current?.focus({
46869
- cursor: "all"
46870
- });
46871
- copyToClipboard();
46872
- }
46873
- },
46874
- value: hidden ? "" : decodedText
47018
+ $hidden: effectiveHidden,
47019
+ onClick: (e) => handleInputClick(e, effectiveHidden, value2),
47020
+ value: shownValue,
47021
+ readOnly: true
46875
47022
  }
46876
47023
  ) }),
46877
- /* @__PURE__ */ jsxRuntimeExports.jsx(antd.Button, { type: "text", onClick: () => setHidden(!hidden), children: hidden ? /* @__PURE__ */ jsxRuntimeExports.jsx(AntIcons.EyeOutlined, {}) : /* @__PURE__ */ jsxRuntimeExports.jsx(AntIcons.EyeInvisibleOutlined, {}) })
46878
- ] }),
47024
+ !hideEye && /* @__PURE__ */ jsxRuntimeExports.jsx(antd.Button, { type: "text", onClick: onToggle, children: isHidden ? /* @__PURE__ */ jsxRuntimeExports.jsx(AntIcons.EyeOutlined, {}) : /* @__PURE__ */ jsxRuntimeExports.jsx(AntIcons.EyeInvisibleOutlined, {}) })
47025
+ ] });
47026
+ };
47027
+ if (reqIndex && jsonPathToSecrets) {
47028
+ const reqIndexPrepared = parseAll({ text: reqIndex, replaceValues, multiQueryData });
47029
+ const jsonPathToSecretsPrepared = parseAll({ text: jsonPathToSecrets, replaceValues, multiQueryData });
47030
+ const jsonRoot = multiQueryData[`req${reqIndexPrepared}`];
47031
+ if (jsonRoot === void 0) {
47032
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: "No root for json path" });
47033
+ }
47034
+ const pathResults = jp.query(jsonRoot || {}, `$${jsonPathToSecretsPrepared}`);
47035
+ const objectToRender = pathResults.find((item) => item !== null && typeof item === "object" && !Array.isArray(item)) || null;
47036
+ const secretsEntries = objectToRender ? Object.entries(objectToRender) : [];
47037
+ if (secretsEntries.length === 0) {
47038
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: containerStyle, children: [
47039
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Styled$s.NotificationOverrides, {}),
47040
+ emptyTextPrepared && /* @__PURE__ */ jsxRuntimeExports.jsx(antd.Typography.Text, { style: textStyle, children: emptyTextPrepared }),
47041
+ contextHolder
47042
+ ] });
47043
+ }
47044
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: containerStyle, children: [
47045
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Styled$s.NotificationOverrides, {}),
47046
+ /* @__PURE__ */ jsxRuntimeExports.jsx(antd.Flex, { vertical: true, gap: 8, children: secretsEntries.map(([key, rawValue]) => {
47047
+ const parsedValue = parseAll({
47048
+ text: typeof rawValue === "string" ? rawValue : String(rawValue),
47049
+ replaceValues,
47050
+ multiQueryData
47051
+ });
47052
+ const shouldDecodeObject = type !== "plain";
47053
+ const secretValue = decodeIfBase64(parsedValue, shouldDecodeObject);
47054
+ const hiddenForKey = hiddenByKey[key] ?? hiddenDefault;
47055
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
47056
+ /* @__PURE__ */ jsxRuntimeExports.jsx(antd.Typography.Text, { strong: true, style: textStyle, children: key }),
47057
+ renderSecretField({
47058
+ value: secretValue,
47059
+ isHidden: hiddenForKey,
47060
+ onToggle: () => setHiddenByKey((prevState) => ({
47061
+ ...prevState,
47062
+ [key]: !(prevState[key] ?? hiddenDefault)
47063
+ }))
47064
+ })
47065
+ ] }, key);
47066
+ }) }),
47067
+ contextHolder
47068
+ ] });
47069
+ }
47070
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: containerStyle, children: [
47071
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Styled$s.NotificationOverrides, {}),
47072
+ renderSecretField({
47073
+ value: decodedText,
47074
+ isHidden: hidden,
47075
+ onToggle: () => setHidden(!hidden)
47076
+ }),
46879
47077
  contextHolder
46880
47078
  ] });
46881
47079
  };
@@ -67835,7 +68033,7 @@ Take a look at the reducer(s) handling this action type: ${action.type}.
67835
68033
  exports.last = last;
67836
68034
  } (last$2));
67837
68035
 
67838
- var toArray$2 = {};
68036
+ var toArray$1 = {};
67839
68037
 
67840
68038
  (function (exports) {
67841
68039
 
@@ -67846,14 +68044,14 @@ Take a look at the reducer(s) handling this action type: ${action.type}.
67846
68044
  }
67847
68045
 
67848
68046
  exports.toArray = toArray;
67849
- } (toArray$2));
68047
+ } (toArray$1));
67850
68048
 
67851
68049
  (function (exports) {
67852
68050
 
67853
68051
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
67854
68052
 
67855
68053
  const last$1 = last$2;
67856
- const toArray = toArray$2;
68054
+ const toArray = toArray$1;
67857
68055
  const isArrayLike$1 = isArrayLike;
67858
68056
 
67859
68057
  function last(array) {
@@ -68399,7 +68597,7 @@ Take a look at the reducer(s) handling this action type: ${action.type}.
68399
68597
  * @param children do not use
68400
68598
  * @return deprecated do not use
68401
68599
  */
68402
- var toArray$1 = children => {
68600
+ var toArray = children => {
68403
68601
  if (children === lastChildren && Array.isArray(lastResult)) {
68404
68602
  return lastResult;
68405
68603
  }
@@ -68407,7 +68605,7 @@ Take a look at the reducer(s) handling this action type: ${action.type}.
68407
68605
  React$1.Children.forEach(children, child => {
68408
68606
  if (isNullish(child)) return;
68409
68607
  if (reactIsExports.isFragment(child)) {
68410
- result = result.concat(toArray$1(child.props.children));
68608
+ result = result.concat(toArray(child.props.children));
68411
68609
  } else {
68412
68610
  // @ts-expect-error this could still be Iterable<ReactNode> and TS does not like that
68413
68611
  result.push(child);
@@ -68436,7 +68634,7 @@ Take a look at the reducer(s) handling this action type: ${action.type}.
68436
68634
  } else {
68437
68635
  types = [getDisplayName(type)];
68438
68636
  }
68439
- toArray$1(children).forEach(child => {
68637
+ toArray(children).forEach(child => {
68440
68638
  // @ts-expect-error toArray and lodash.get are not compatible. Let's get rid of the whole findAllByType function
68441
68639
  var childType = get$1(child, 'type.displayName') || get$1(child, 'type.name');
68442
68640
  if (childType && types.indexOf(childType) !== -1) {
@@ -79208,6 +79406,28 @@ Take a look at the reducer(s) handling this action type: ${action.type}.
79208
79406
  ] });
79209
79407
  };
79210
79408
 
79409
+ const ACTION_REQUIRED_PERMISSIONS = {
79410
+ edit: { verb: "update" },
79411
+ editLabels: { verb: "patch" },
79412
+ editAnnotations: { verb: "patch" },
79413
+ editTaints: { verb: "patch" },
79414
+ editTolerations: { verb: "patch" },
79415
+ delete: { verb: "delete" },
79416
+ cordon: { verb: "patch" },
79417
+ uncordon: { verb: "patch" },
79418
+ suspend: { verb: "patch" },
79419
+ resume: { verb: "patch" },
79420
+ rolloutRestart: { verb: "patch" },
79421
+ evict: { verb: "create", subresource: "eviction" },
79422
+ openKubeletConfig: { verb: "get", subresource: "proxy" },
79423
+ scale: { verb: "update", subresource: "scale" },
79424
+ triggerRun: { verb: "create" },
79425
+ deleteChildren: { verb: "delete" },
79426
+ rerunLast: { verb: "create" },
79427
+ drain: { verb: "patch" },
79428
+ rollback: { verb: "patch" }
79429
+ };
79430
+
79211
79431
  const IconWrapper = styled.span`
79212
79432
  display: inline-flex;
79213
79433
  width: 14px;
@@ -79232,45 +79452,29 @@ Take a look at the reducer(s) handling this action type: ${action.type}.
79232
79452
  IconButton
79233
79453
  };
79234
79454
 
79235
- const ACTION_REQUIRED_PERMISSIONS = {
79236
- edit: { verb: "update" },
79237
- editLabels: { verb: "patch" },
79238
- editAnnotations: { verb: "patch" },
79239
- editTaints: { verb: "patch" },
79240
- editTolerations: { verb: "patch" },
79241
- delete: { verb: "delete" },
79242
- cordon: { verb: "patch" },
79243
- uncordon: { verb: "patch" },
79244
- suspend: { verb: "patch" },
79245
- resume: { verb: "patch" },
79246
- rolloutRestart: { verb: "patch" },
79247
- evict: { verb: "create", subresource: "eviction" },
79248
- openKubeletConfig: { verb: "get", subresource: "proxy" }
79249
- };
79250
- const toArray = (value) => Array.isArray(value) ? value : [value];
79251
- const getRequiredPermissions = (actions) => {
79252
- return actions.flatMap((action) => toArray(ACTION_REQUIRED_PERMISSIONS[action.type]));
79253
- };
79254
79455
  const UNDEFINED_FALLBACK = "Undefined with no fallback";
79255
79456
  const isMeaningfulValue = (value) => value.length > 0 && value !== "-" && value !== UNDEFINED_FALLBACK;
79256
79457
  const getVisibleActions = (actions, { replaceValues, multiQueryData }) => {
79257
- return actions.filter((action) => {
79458
+ return actions.flatMap((action, index) => {
79258
79459
  const condition = action.props.visibleWhen;
79259
- if (!condition) return true;
79460
+ if (!condition) {
79461
+ return [{ action, actionKey: `${action.type}-${index}` }];
79462
+ }
79260
79463
  const currentValue = parseAll({ text: condition.value, replaceValues, multiQueryData });
79261
79464
  const hasValue = isMeaningfulValue(currentValue);
79262
79465
  if (condition.criteria === "exists") {
79263
- return hasValue;
79466
+ return hasValue ? [{ action, actionKey: `${action.type}-${index}` }] : [];
79264
79467
  }
79265
79468
  if (condition.criteria === "notExists") {
79266
- return !hasValue;
79469
+ return !hasValue ? [{ action, actionKey: `${action.type}-${index}` }] : [];
79267
79470
  }
79268
79471
  if (condition.valueToCompare === void 0) {
79269
- return true;
79472
+ return [{ action, actionKey: `${action.type}-${index}` }];
79270
79473
  }
79271
79474
  const expectedValues = (Array.isArray(condition.valueToCompare) ? condition.valueToCompare : [condition.valueToCompare]).map((value) => parseAll({ text: value, replaceValues, multiQueryData }));
79272
79475
  const matches = expectedValues.includes(currentValue);
79273
- return condition.criteria === "equals" ? matches : !matches;
79476
+ const isVisible = condition.criteria === "equals" ? matches : !matches;
79477
+ return isVisible ? [{ action, actionKey: `${action.type}-${index}` }] : [];
79274
79478
  });
79275
79479
  };
79276
79480
  const buildEditUrl = (props, fullPath) => {
@@ -79299,35 +79503,14 @@ Take a look at the reducer(s) handling this action type: ${action.type}.
79299
79503
  }
79300
79504
  return void 0;
79301
79505
  };
79302
- const isActionDisabledByPermission = (action, permissions) => {
79303
- switch (action.type) {
79304
- case "edit":
79305
- return permissions.canUpdate !== true;
79306
- case "editLabels":
79307
- case "editAnnotations":
79308
- case "editTaints":
79309
- case "editTolerations":
79310
- case "cordon":
79311
- case "uncordon":
79312
- case "suspend":
79313
- case "resume":
79314
- case "rolloutRestart":
79315
- return permissions.canPatch !== true;
79316
- case "delete":
79317
- return permissions.canDelete !== true;
79318
- case "evict":
79319
- return permissions.canCreate !== true;
79320
- case "openKubeletConfig":
79321
- return permissions.canGet !== true;
79322
- default:
79323
- return true;
79324
- }
79506
+ const isActionDisabledByPermission = (actionKey, permissions) => {
79507
+ return permissions[actionKey] !== true;
79325
79508
  };
79326
- const getMenuItems = (actions, onActionClick, permissions) => actions.map((action, index) => ({
79327
- key: `${action.type}-${index}`,
79509
+ const getMenuItems = (visibleActions, onActionClick, permissions) => visibleActions.map(({ action, actionKey }) => ({
79510
+ key: actionKey,
79328
79511
  label: action.props.tooltip ? /* @__PURE__ */ jsxRuntimeExports.jsx(antd.Tooltip, { title: action.props.tooltip, children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: action.props.text }) }) : action.props.text,
79329
79512
  icon: getActionIcon(action),
79330
- disabled: action.props.disabled || isActionDisabledByPermission(action, permissions),
79513
+ disabled: action.props.disabled || isActionDisabledByPermission(actionKey, permissions),
79331
79514
  danger: action.props.danger,
79332
79515
  onClick: () => onActionClick(action)
79333
79516
  }));
@@ -79338,6 +79521,18 @@ Take a look at the reducer(s) handling this action type: ${action.type}.
79338
79521
  }
79339
79522
  return value;
79340
79523
  };
79524
+ const resolveObjectFromTemplate = (template, multiQueryData) => {
79525
+ const match = template.match(/^\{reqs\[(\d+)\]\[((?:\s*['"][^'"]+['"]\s*,?)+)\]\}$/);
79526
+ if (match) {
79527
+ const reqIndex = parseInt(match[1], 10);
79528
+ const pathKeys = Array.from(match[2].matchAll(/['"]([^'"]+)['"]/g)).map((m) => m[1]);
79529
+ const reqData = multiQueryData[`req${reqIndex}`];
79530
+ if (reqData != null) {
79531
+ return _$1.get(reqData, pathKeys);
79532
+ }
79533
+ }
79534
+ return void 0;
79535
+ };
79341
79536
  const buildEvictModalData = (props, ctx) => {
79342
79537
  const endpointPrepared = parseAll({ text: props.endpoint, ...ctx });
79343
79538
  const namePrepared = parseAll({ text: props.name, ...ctx });
@@ -79370,6 +79565,35 @@ Take a look at the reducer(s) handling this action type: ${action.type}.
79370
79565
  ...Object.keys(deleteOptions).length > 0 ? { deleteOptions } : {}
79371
79566
  };
79372
79567
  };
79568
+ const buildDeleteChildrenData = (action, ctx) => {
79569
+ const childResourceNamePrepared = parseAll({ text: action.props.childResourceName, ...ctx });
79570
+ const childrenTemplatePrepared = parseWithoutPartsOfUrl({
79571
+ text: action.props.children,
79572
+ multiQueryData: ctx.multiQueryData
79573
+ });
79574
+ let parsedChildren;
79575
+ try {
79576
+ parsedChildren = JSON.parse(childrenTemplatePrepared);
79577
+ } catch {
79578
+ throw new Error("Could not parse children data");
79579
+ }
79580
+ if (!Array.isArray(parsedChildren)) {
79581
+ throw new Error("No children found to delete");
79582
+ }
79583
+ const children = parsedChildren.filter(
79584
+ (el) => typeof el === "object" && el !== null && typeof el.name === "string" && typeof el.endpoint === "string"
79585
+ ).map((el) => ({
79586
+ name: parsePartsOfUrl({ template: el.name, replaceValues: ctx.replaceValues }),
79587
+ endpoint: parsePartsOfUrl({ template: el.endpoint, replaceValues: ctx.replaceValues })
79588
+ }));
79589
+ if (children.length === 0) {
79590
+ throw new Error("No children found to delete");
79591
+ }
79592
+ return {
79593
+ children,
79594
+ childResourceName: childResourceNamePrepared
79595
+ };
79596
+ };
79373
79597
  const handleEditAction = (action, ctx, fullPath, navigate) => {
79374
79598
  const clusterPrepared = parseAll({ text: action.props.cluster, ...ctx });
79375
79599
  const namespacePrepared = action.props.namespace ? parseAll({ text: action.props.namespace, ...ctx }) : void 0;
@@ -79438,7 +79662,6 @@ Take a look at the reducer(s) handling this action type: ${action.type}.
79438
79662
  }
79439
79663
  }).then(() => onSuccess(actionLabel)).catch((error) => {
79440
79664
  onError(actionLabel, error);
79441
- console.error(error);
79442
79665
  });
79443
79666
  };
79444
79667
  const handleOpenKubeletConfigAction = (action, ctx, setActiveAction, setModalOpen) => {
@@ -79456,6 +79679,183 @@ Take a look at the reducer(s) handling this action type: ${action.type}.
79456
79679
  });
79457
79680
  setModalOpen(true);
79458
79681
  };
79682
+ const generateDnsCompliantName = (prefix, maxLength = 63) => {
79683
+ const timestamp = Date.now();
79684
+ const randomHex = Math.random().toString(16).substring(2, 6);
79685
+ const suffix = `-${timestamp}-${randomHex}`;
79686
+ const truncatedPrefix = prefix.substring(0, maxLength - suffix.length);
79687
+ return `${truncatedPrefix}${suffix}`.toLowerCase().replace(/[^a-z0-9-]/g, "-");
79688
+ };
79689
+ const JOB_MANAGED_LABEL_KEYS = [
79690
+ "controller-uid",
79691
+ "job-name",
79692
+ "batch.kubernetes.io/controller-uid",
79693
+ "batch.kubernetes.io/job-name"
79694
+ ];
79695
+ const stripManagedJobLabels = (labels) => {
79696
+ if (!labels || typeof labels !== "object" || Array.isArray(labels)) {
79697
+ return void 0;
79698
+ }
79699
+ const cleaned = { ...labels };
79700
+ JOB_MANAGED_LABEL_KEYS.forEach((key) => delete cleaned[key]);
79701
+ return Object.keys(cleaned).length > 0 ? cleaned : void 0;
79702
+ };
79703
+ const stripMetadataForRerun = (sourceObj, sourceJobName) => {
79704
+ const normalizedSourceObj = _$1.isPlainObject(_$1.get(sourceObj, "spec")) ? sourceObj : _$1.isPlainObject(sourceObj) && _$1.isPlainObject(_$1.get(sourceObj, "template")) ? { spec: sourceObj } : sourceObj;
79705
+ const copy = JSON.parse(JSON.stringify(normalizedSourceObj));
79706
+ const oldMeta = copy.metadata ?? {};
79707
+ const cleanedMetadataLabels = stripManagedJobLabels(oldMeta.labels);
79708
+ copy.metadata = {
79709
+ ...oldMeta.namespace ? { namespace: oldMeta.namespace } : {},
79710
+ ...cleanedMetadataLabels ? { labels: cleanedMetadataLabels } : {},
79711
+ ...oldMeta.annotations ? { annotations: oldMeta.annotations } : {},
79712
+ generateName: `${sourceJobName}-rerun-`
79713
+ };
79714
+ const spec = _$1.get(copy, "spec");
79715
+ if (_$1.isPlainObject(spec)) {
79716
+ const specObj = spec;
79717
+ delete specObj.selector;
79718
+ delete specObj.manualSelector;
79719
+ }
79720
+ const templateLabels = _$1.get(copy, "spec.template.metadata.labels");
79721
+ if (_$1.isPlainObject(templateLabels)) {
79722
+ const cleanedTemplateLabels = stripManagedJobLabels(templateLabels);
79723
+ if (cleanedTemplateLabels) {
79724
+ _$1.set(copy, "spec.template.metadata.labels", cleanedTemplateLabels);
79725
+ } else {
79726
+ _$1.unset(copy, "spec.template.metadata.labels");
79727
+ }
79728
+ }
79729
+ delete copy.status;
79730
+ return copy;
79731
+ };
79732
+ const useScaleHandlers = (ctx, { showSuccess, showError }) => {
79733
+ const [scaleModalData, setScaleModalData] = React$1.useState(null);
79734
+ const [isScaleLoading, setIsScaleLoading] = React$1.useState(false);
79735
+ const handleScaleAction = (action) => {
79736
+ const endpointPrepared = parseAll({ text: action.props.endpoint, ...ctx });
79737
+ const namePrepared = parseAll({ text: action.props.name, ...ctx });
79738
+ const namespacePrepared = action.props.namespace ? parseAll({ text: action.props.namespace, ...ctx }) : void 0;
79739
+ const apiVersionPrepared = action.props.apiVersion ? parseAll({ text: action.props.apiVersion, ...ctx }) : "autoscaling/v1";
79740
+ const currentReplicasStr = parseAll({ text: action.props.currentReplicas, ...ctx });
79741
+ const currentReplicas = parseInt(currentReplicasStr, 10) || 0;
79742
+ setScaleModalData({
79743
+ endpoint: endpointPrepared,
79744
+ currentReplicas,
79745
+ name: namePrepared,
79746
+ namespace: namespacePrepared,
79747
+ apiVersion: apiVersionPrepared
79748
+ });
79749
+ };
79750
+ const handleScaleConfirm = (newReplicas) => {
79751
+ if (!scaleModalData) return;
79752
+ setIsScaleLoading(true);
79753
+ const body = {
79754
+ apiVersion: scaleModalData.apiVersion,
79755
+ kind: "Scale",
79756
+ metadata: {
79757
+ name: scaleModalData.name,
79758
+ ...scaleModalData.namespace ? { namespace: scaleModalData.namespace } : {}
79759
+ },
79760
+ spec: { replicas: newReplicas }
79761
+ };
79762
+ const scaleLabel = `Scale ${scaleModalData.name}`;
79763
+ updateEntry({ endpoint: scaleModalData.endpoint, body }).then(() => showSuccess(scaleLabel)).catch((error) => {
79764
+ showError(scaleLabel, error);
79765
+ }).finally(() => {
79766
+ setIsScaleLoading(false);
79767
+ setScaleModalData(null);
79768
+ });
79769
+ };
79770
+ const handleScaleCancel = () => {
79771
+ setScaleModalData(null);
79772
+ setIsScaleLoading(false);
79773
+ };
79774
+ return { scaleModalData, isScaleLoading, handleScaleAction, handleScaleConfirm, handleScaleCancel };
79775
+ };
79776
+ const useEvictHandlers = ({ showSuccess, showError }) => {
79777
+ const [evictModalData, setEvictModalData] = React$1.useState(null);
79778
+ const [isEvictLoading, setIsEvictLoading] = React$1.useState(false);
79779
+ const handleEvictConfirm = () => {
79780
+ if (!evictModalData) return;
79781
+ setIsEvictLoading(true);
79782
+ const body = buildEvictBody(evictModalData);
79783
+ const evictLabel = `Evict ${evictModalData.name}`;
79784
+ createNewEntry({ endpoint: evictModalData.endpoint, body }).then(() => showSuccess(evictLabel)).catch((error) => {
79785
+ showError(evictLabel, error);
79786
+ }).finally(() => {
79787
+ setIsEvictLoading(false);
79788
+ setEvictModalData(null);
79789
+ });
79790
+ };
79791
+ const handleEvictCancel = () => {
79792
+ setEvictModalData(null);
79793
+ setIsEvictLoading(false);
79794
+ };
79795
+ return { evictModalData, isEvictLoading, setEvictModalData, handleEvictConfirm, handleEvictCancel };
79796
+ };
79797
+ const useRerunHandlers = (ctx, multiQueryData, { showSuccess, showError }) => {
79798
+ const [rerunModalData, setRerunModalData] = React$1.useState(null);
79799
+ const [isRerunLoading, setIsRerunLoading] = React$1.useState(false);
79800
+ const handleRerunLastAction = (action) => {
79801
+ const createEndpointPrepared = parseAll({ text: action.props.createEndpoint, ...ctx });
79802
+ const sourceJobNamePrepared = parseAll({ text: action.props.sourceJobName, ...ctx });
79803
+ const sourceJobObj = resolveObjectFromTemplate(action.props.sourceJobSpec, multiQueryData);
79804
+ if (!sourceJobObj) {
79805
+ showError("Rerun job", new Error("Could not resolve source job spec from resource data"));
79806
+ return;
79807
+ }
79808
+ setRerunModalData({
79809
+ createEndpoint: createEndpointPrepared,
79810
+ sourceName: sourceJobNamePrepared,
79811
+ sourceSpec: sourceJobObj
79812
+ });
79813
+ };
79814
+ const handleRerunConfirm = () => {
79815
+ if (!rerunModalData) return;
79816
+ setIsRerunLoading(true);
79817
+ const body = stripMetadataForRerun(rerunModalData.sourceSpec, rerunModalData.sourceName);
79818
+ const rerunLabel = `Rerun ${rerunModalData.sourceName}`;
79819
+ createNewEntry({ endpoint: rerunModalData.createEndpoint, body }).then(() => showSuccess(rerunLabel)).catch((error) => {
79820
+ showError(rerunLabel, error);
79821
+ }).finally(() => {
79822
+ setIsRerunLoading(false);
79823
+ setRerunModalData(null);
79824
+ });
79825
+ };
79826
+ const handleRerunCancel = () => {
79827
+ setRerunModalData(null);
79828
+ setIsRerunLoading(false);
79829
+ };
79830
+ return { rerunModalData, isRerunLoading, handleRerunLastAction, handleRerunConfirm, handleRerunCancel };
79831
+ };
79832
+ const fireTriggerRunAction = (action, ctx, multiQueryData, { showSuccess, showError }) => {
79833
+ const createEndpointPrepared = parseAll({ text: action.props.createEndpoint, ...ctx });
79834
+ const cronJobNamePrepared = parseAll({ text: action.props.cronJobName, ...ctx });
79835
+ const jobTemplateObj = resolveObjectFromTemplate(action.props.jobTemplate, multiQueryData);
79836
+ if (!jobTemplateObj) {
79837
+ showError("Trigger run", new Error("Could not resolve job template from resource data"));
79838
+ return;
79839
+ }
79840
+ const jobName = generateDnsCompliantName(`${cronJobNamePrepared}-manual`);
79841
+ const namespaceParsed = cronJobNamePrepared ? _$1.get(jobTemplateObj, ["metadata", "namespace"]) : void 0;
79842
+ const body = {
79843
+ apiVersion: "batch/v1",
79844
+ kind: "Job",
79845
+ metadata: {
79846
+ name: jobName,
79847
+ ...namespaceParsed ? { namespace: namespaceParsed } : {},
79848
+ annotations: {
79849
+ "cronjob.kubernetes.io/instantiate": "manual"
79850
+ }
79851
+ },
79852
+ spec: jobTemplateObj.spec
79853
+ };
79854
+ const triggerLabel = `Trigger run for ${cronJobNamePrepared}`;
79855
+ createNewEntry({ endpoint: createEndpointPrepared, body }).then(() => showSuccess(triggerLabel)).catch((error) => {
79856
+ showError(triggerLabel, error);
79857
+ });
79858
+ };
79459
79859
  const useActionsDropdownHandlers = ({ replaceValues, multiQueryData }) => {
79460
79860
  const navigate = reactRouterDom.useNavigate();
79461
79861
  const location = reactRouterDom.useLocation();
@@ -79466,8 +79866,7 @@ Take a look at the reducer(s) handling this action type: ${action.type}.
79466
79866
  const [activeAction, setActiveAction] = React$1.useState(null);
79467
79867
  const [modalOpen, setModalOpen] = React$1.useState(false);
79468
79868
  const [deleteModalData, setDeleteModalData] = React$1.useState(null);
79469
- const [evictModalData, setEvictModalData] = React$1.useState(null);
79470
- const [isEvictLoading, setIsEvictLoading] = React$1.useState(false);
79869
+ const [deleteChildrenModalData, setDeleteChildrenModalData] = React$1.useState(null);
79471
79870
  const invalidateMultiQuery = () => {
79472
79871
  queryClient.invalidateQueries({ queryKey: ["multi"] });
79473
79872
  };
@@ -79495,6 +79894,26 @@ Take a look at the reducer(s) handling this action type: ${action.type}.
79495
79894
  });
79496
79895
  };
79497
79896
  const ctx = { replaceValues, multiQueryData };
79897
+ const notificationCallbacks = { showSuccess, showError };
79898
+ const { scaleModalData, isScaleLoading, handleScaleAction, handleScaleConfirm, handleScaleCancel } = useScaleHandlers(
79899
+ ctx,
79900
+ notificationCallbacks
79901
+ );
79902
+ const { evictModalData, isEvictLoading, setEvictModalData, handleEvictConfirm, handleEvictCancel } = useEvictHandlers(notificationCallbacks);
79903
+ const { rerunModalData, isRerunLoading, handleRerunLastAction, handleRerunConfirm, handleRerunCancel } = useRerunHandlers(ctx, multiQueryData, notificationCallbacks);
79904
+ const handleDeleteChildrenAction = (action) => {
79905
+ try {
79906
+ const data = buildDeleteChildrenData(action, ctx);
79907
+ setDeleteChildrenModalData(data);
79908
+ } catch (error) {
79909
+ const childResourceNamePrepared = parseAll({ text: action.props.childResourceName, ...ctx });
79910
+ showError(`Delete ${childResourceNamePrepared}`, error);
79911
+ }
79912
+ };
79913
+ const handleDeleteChildrenClose = () => {
79914
+ setDeleteChildrenModalData(null);
79915
+ invalidateMultiQuery();
79916
+ };
79498
79917
  const handleActionClick = (action) => {
79499
79918
  if (action.type === "edit") {
79500
79919
  handleEditAction(action, ctx, fullPath, navigate);
@@ -79521,25 +79940,28 @@ Take a look at the reducer(s) handling this action type: ${action.type}.
79521
79940
  handleOpenKubeletConfigAction(action, ctx, setActiveAction, setModalOpen);
79522
79941
  return;
79523
79942
  }
79943
+ if (action.type === "scale") {
79944
+ handleScaleAction(action);
79945
+ return;
79946
+ }
79947
+ if (action.type === "triggerRun") {
79948
+ fireTriggerRunAction(action, ctx, multiQueryData, notificationCallbacks);
79949
+ return;
79950
+ }
79951
+ if (action.type === "deleteChildren") {
79952
+ handleDeleteChildrenAction(action);
79953
+ return;
79954
+ }
79955
+ if (action.type === "rerunLast") {
79956
+ handleRerunLastAction(action);
79957
+ return;
79958
+ }
79959
+ if (action.type === "drain" || action.type === "rollback") {
79960
+ return;
79961
+ }
79524
79962
  setActiveAction(action);
79525
79963
  setModalOpen(true);
79526
79964
  };
79527
- const handleEvictConfirm = () => {
79528
- if (!evictModalData) return;
79529
- setIsEvictLoading(true);
79530
- const body = buildEvictBody(evictModalData);
79531
- const evictLabel = `Evict ${evictModalData.name}`;
79532
- createNewEntry({ endpoint: evictModalData.endpoint, body }).then(() => showSuccess(evictLabel)).catch((error) => {
79533
- showError(evictLabel, error);
79534
- }).finally(() => {
79535
- setIsEvictLoading(false);
79536
- setEvictModalData(null);
79537
- });
79538
- };
79539
- const handleEvictCancel = () => {
79540
- setEvictModalData(null);
79541
- setIsEvictLoading(false);
79542
- };
79543
79965
  const handleCloseModal = () => {
79544
79966
  setModalOpen(false);
79545
79967
  setActiveAction(null);
@@ -79561,78 +79983,122 @@ Take a look at the reducer(s) handling this action type: ${action.type}.
79561
79983
  deleteModalData,
79562
79984
  evictModalData,
79563
79985
  isEvictLoading,
79986
+ scaleModalData,
79987
+ isScaleLoading,
79988
+ deleteChildrenModalData,
79989
+ rerunModalData,
79990
+ isRerunLoading,
79564
79991
  handleActionClick,
79565
79992
  handleCloseModal,
79566
79993
  handleDeleteModalClose,
79567
79994
  handleEvictConfirm,
79568
- handleEvictCancel
79995
+ handleEvictCancel,
79996
+ handleScaleConfirm,
79997
+ handleScaleCancel,
79998
+ handleDeleteChildrenClose,
79999
+ handleRerunConfirm,
80000
+ handleRerunCancel
79569
80001
  };
79570
80002
  };
79571
80003
 
80004
+ const buildCacheKey = (slot) => `${slot.cluster}|${slot.namespace ?? ""}|${slot.apiGroup ?? ""}|${slot.plural}|${slot.subresource ?? ""}|${slot.verb}`;
80005
+ const parsePermissionContext = (ctx, parseCtx) => ({
80006
+ cluster: parseAll({ text: ctx.cluster, ...parseCtx }),
80007
+ namespace: ctx.namespace ? parseAll({ text: ctx.namespace, ...parseCtx }) : void 0,
80008
+ apiGroup: ctx.apiGroup ? parseAll({ text: ctx.apiGroup, ...parseCtx }) : void 0,
80009
+ plural: parseAll({ text: ctx.plural, ...parseCtx }),
80010
+ subresource: ctx.subresource ? parseAll({ text: ctx.subresource, ...parseCtx }) : void 0
80011
+ });
80012
+ const isValidContext = (parsed) => !!parsed.cluster && parsed.cluster !== "-" && !!parsed.plural && parsed.plural !== "-";
80013
+ const useManyPermissions = (slots, enabled) => {
80014
+ return reactQuery.useQueries({
80015
+ queries: slots.map((slot) => ({
80016
+ queryKey: [
80017
+ "usePermissions",
80018
+ slot.cluster,
80019
+ slot.namespace,
80020
+ slot.apiGroup,
80021
+ slot.plural,
80022
+ slot.subresource,
80023
+ slot.verb,
80024
+ void 0
80025
+ ],
80026
+ queryFn: async () => (await checkPermission({
80027
+ cluster: slot.cluster,
80028
+ body: {
80029
+ namespace: slot.namespace,
80030
+ apiGroup: slot.apiGroup,
80031
+ plural: slot.plural,
80032
+ subresource: slot.subresource,
80033
+ verb: slot.verb
80034
+ }
80035
+ })).data,
80036
+ refetchInterval: false,
80037
+ enabled
80038
+ }))
80039
+ });
80040
+ };
79572
80041
  const useActionsDropdownPermissions = ({
79573
80042
  actions,
79574
80043
  permissions,
79575
- permissionContext,
79576
80044
  replaceValues,
79577
80045
  multiQueryData,
79578
80046
  isMultiQueryLoading
79579
80047
  }) => {
79580
- const permissionContextPrepared = permissionContext ? {
79581
- cluster: parseAll({ text: permissionContext.cluster, replaceValues, multiQueryData }),
79582
- namespace: permissionContext.namespace ? parseAll({ text: permissionContext.namespace, replaceValues, multiQueryData }) : void 0,
79583
- apiGroup: permissionContext.apiGroup ? parseAll({ text: permissionContext.apiGroup, replaceValues, multiQueryData }) : void 0,
79584
- plural: parseAll({ text: permissionContext.plural, replaceValues, multiQueryData })
79585
- } : void 0;
79586
- const isPermissionContextValid = !!permissionContextPrepared && !isMultiQueryLoading && !!permissionContextPrepared.cluster && permissionContextPrepared.cluster !== "-" && !!permissionContextPrepared.plural && permissionContextPrepared.plural !== "-";
79587
80048
  const shouldCheckPermissions = !permissions;
79588
- const requiredPermissions = shouldCheckPermissions ? getRequiredPermissions(actions) : [];
79589
- const requiredVerbs = new Set(requiredPermissions.map((permission) => permission.verb));
79590
- const getSubresourceForVerb = (verb) => requiredPermissions.find((p) => p.verb === verb && p.subresource)?.subresource;
79591
- const permissionBaseParams = {
79592
- cluster: permissionContextPrepared?.cluster || "",
79593
- namespace: permissionContextPrepared?.namespace,
79594
- apiGroup: permissionContextPrepared?.apiGroup,
79595
- plural: permissionContextPrepared?.plural || "",
79596
- refetchInterval: false
79597
- };
79598
- const updatePermission = usePermissions({
79599
- ...permissionBaseParams,
79600
- verb: "update",
79601
- subresource: getSubresourceForVerb("update"),
79602
- enabler: shouldCheckPermissions && isPermissionContextValid && requiredVerbs.has("update")
79603
- });
79604
- const patchPermission = usePermissions({
79605
- ...permissionBaseParams,
79606
- verb: "patch",
79607
- subresource: getSubresourceForVerb("patch"),
79608
- enabler: shouldCheckPermissions && isPermissionContextValid && requiredVerbs.has("patch")
79609
- });
79610
- const deletePermission = usePermissions({
79611
- ...permissionBaseParams,
79612
- verb: "delete",
79613
- subresource: getSubresourceForVerb("delete"),
79614
- enabler: shouldCheckPermissions && isPermissionContextValid && requiredVerbs.has("delete")
79615
- });
79616
- const createPermission = usePermissions({
79617
- ...permissionBaseParams,
79618
- verb: "create",
79619
- subresource: getSubresourceForVerb("create"),
79620
- enabler: shouldCheckPermissions && isPermissionContextValid && requiredVerbs.has("create")
79621
- });
79622
- const getPermission = usePermissions({
79623
- ...permissionBaseParams,
79624
- verb: "get",
79625
- subresource: getSubresourceForVerb("get"),
79626
- enabler: shouldCheckPermissions && isPermissionContextValid && requiredVerbs.has("get")
80049
+ const { slots, mappings } = React$1.useMemo(() => {
80050
+ if (!shouldCheckPermissions || isMultiQueryLoading) {
80051
+ return {
80052
+ slots: [],
80053
+ mappings: []
80054
+ };
80055
+ }
80056
+ const parseCtx = { replaceValues, multiQueryData };
80057
+ const uniqueSlots = [];
80058
+ const cacheKeyToIndex = /* @__PURE__ */ new Map();
80059
+ const actionMappings = [];
80060
+ actions.forEach((action, index) => {
80061
+ const actionKey = `${action.type}-${index}`;
80062
+ const permCtx = action.props.permissionContext;
80063
+ if (!permCtx) {
80064
+ return;
80065
+ }
80066
+ const parsed = parsePermissionContext(permCtx, parseCtx);
80067
+ if (!isValidContext(parsed)) {
80068
+ return;
80069
+ }
80070
+ const requiredPerm = ACTION_REQUIRED_PERMISSIONS[action.type];
80071
+ const subresource = requiredPerm.subresource ?? parsed.subresource;
80072
+ const slotData = {
80073
+ cluster: parsed.cluster,
80074
+ namespace: parsed.namespace,
80075
+ apiGroup: parsed.apiGroup,
80076
+ plural: parsed.plural,
80077
+ subresource,
80078
+ verb: requiredPerm.verb
80079
+ };
80080
+ const cacheKey = buildCacheKey(slotData);
80081
+ let slotIndex = cacheKeyToIndex.get(cacheKey);
80082
+ if (slotIndex === void 0) {
80083
+ slotIndex = uniqueSlots.length;
80084
+ uniqueSlots.push({ ...slotData, cacheKey });
80085
+ cacheKeyToIndex.set(cacheKey, slotIndex);
80086
+ }
80087
+ actionMappings.push({ actionKey, slotIndex });
80088
+ });
80089
+ return { slots: uniqueSlots, mappings: actionMappings };
80090
+ }, [shouldCheckPermissions, isMultiQueryLoading, actions, replaceValues, multiQueryData]);
80091
+ const enabled = shouldCheckPermissions && !isMultiQueryLoading;
80092
+ const slotResults = useManyPermissions(slots, enabled);
80093
+ if (permissions) {
80094
+ return permissions;
80095
+ }
80096
+ const computed = {};
80097
+ mappings.forEach((mapping) => {
80098
+ const result = slotResults[mapping.slotIndex];
80099
+ computed[mapping.actionKey] = result?.data?.status?.allowed;
79627
80100
  });
79628
- const computedPermissions = {
79629
- canUpdate: requiredVerbs.has("update") ? updatePermission.data?.status.allowed : void 0,
79630
- canPatch: requiredVerbs.has("patch") ? patchPermission.data?.status.allowed : void 0,
79631
- canDelete: requiredVerbs.has("delete") ? deletePermission.data?.status.allowed : void 0,
79632
- canCreate: requiredVerbs.has("create") ? createPermission.data?.status.allowed : void 0,
79633
- canGet: requiredVerbs.has("get") ? getPermission.data?.status.allowed : void 0
79634
- };
79635
- return permissions ?? computedPermissions;
80101
+ return computed;
79636
80102
  };
79637
80103
 
79638
80104
  const toYamlString = (value) => {
@@ -79718,6 +80184,13 @@ Take a look at the reducer(s) handling this action type: ${action.type}.
79718
80184
  return null;
79719
80185
  case "openKubeletConfig":
79720
80186
  return /* @__PURE__ */ jsxRuntimeExports.jsx(OpenKubeletConfigModal, { ...extraProps, props: action.props });
80187
+ case "scale":
80188
+ case "triggerRun":
80189
+ case "deleteChildren":
80190
+ case "rerunLast":
80191
+ case "drain":
80192
+ case "rollback":
80193
+ return null;
79721
80194
  default: {
79722
80195
  const _exhaustive = action;
79723
80196
  return _exhaustive;
@@ -79725,15 +80198,55 @@ Take a look at the reducer(s) handling this action type: ${action.type}.
79725
80198
  }
79726
80199
  };
79727
80200
 
80201
+ const ScaleModal = ({ open, onClose, onConfirm, currentReplicas, name, isLoading }) => {
80202
+ const [replicas, setReplicas] = React$1.useState(currentReplicas);
80203
+ React$1.useEffect(() => {
80204
+ if (open) {
80205
+ setReplicas(currentReplicas);
80206
+ }
80207
+ }, [open, currentReplicas]);
80208
+ const isValidReplicas = Number.isInteger(replicas) && (replicas ?? -1) >= 0;
80209
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(
80210
+ antd.Modal,
80211
+ {
80212
+ title: `Scale «${name}»`,
80213
+ open,
80214
+ onOk: () => {
80215
+ if (isValidReplicas) {
80216
+ onConfirm(replicas);
80217
+ }
80218
+ },
80219
+ onCancel: onClose,
80220
+ okText: "Scale",
80221
+ confirmLoading: isLoading,
80222
+ okButtonProps: { disabled: !isValidReplicas },
80223
+ width: 400,
80224
+ children: [
80225
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(antd.Typography.Paragraph, { children: [
80226
+ "Current replicas: ",
80227
+ /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: currentReplicas })
80228
+ ] }),
80229
+ /* @__PURE__ */ jsxRuntimeExports.jsx(antd.Typography.Paragraph, { children: "New replicas:" }),
80230
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
80231
+ antd.InputNumber,
80232
+ {
80233
+ min: 0,
80234
+ precision: 0,
80235
+ step: 1,
80236
+ value: replicas,
80237
+ parser: (value) => Number(value ? value.replace(/[^\d]/g, "") : 0),
80238
+ onChange: (value) => setReplicas(typeof value === "number" ? value : null),
80239
+ style: { width: "100%" },
80240
+ autoFocus: true
80241
+ }
80242
+ )
80243
+ ]
80244
+ }
80245
+ );
80246
+ };
80247
+
79728
80248
  const ActionsDropdown = ({ data, children }) => {
79729
- const {
79730
- buttonText = "Actions",
79731
- buttonVariant = "default",
79732
- containerStyle,
79733
- actions,
79734
- permissions,
79735
- permissionContext
79736
- } = data;
80249
+ const { buttonText = "Actions", buttonVariant = "default", containerStyle, actions, permissions } = data;
79737
80250
  const { data: multiQueryData, isLoading: isMultiQueryLoading, isError: isMultiQueryError, errors } = useMultiQuery();
79738
80251
  const partsOfUrl = usePartsOfUrl();
79739
80252
  const replaceValues = partsOfUrl.partsOfUrl.reduce((acc, value, index) => {
@@ -79741,18 +80254,17 @@ Take a look at the reducer(s) handling this action type: ${action.type}.
79741
80254
  return acc;
79742
80255
  }, {});
79743
80256
  const safeMultiQueryData = multiQueryData ?? {};
79744
- const visibleActions = getVisibleActions(actions, {
79745
- replaceValues,
79746
- multiQueryData: safeMultiQueryData
79747
- });
79748
80257
  const effectivePermissions = useActionsDropdownPermissions({
79749
- actions: visibleActions,
80258
+ actions,
79750
80259
  permissions,
79751
- permissionContext,
79752
80260
  replaceValues,
79753
80261
  multiQueryData: safeMultiQueryData,
79754
80262
  isMultiQueryLoading
79755
80263
  });
80264
+ const visibleActions = getVisibleActions(actions, {
80265
+ replaceValues,
80266
+ multiQueryData: safeMultiQueryData
80267
+ });
79756
80268
  const {
79757
80269
  notificationContextHolder,
79758
80270
  activeAction,
@@ -79760,11 +80272,21 @@ Take a look at the reducer(s) handling this action type: ${action.type}.
79760
80272
  deleteModalData,
79761
80273
  evictModalData,
79762
80274
  isEvictLoading,
80275
+ scaleModalData,
80276
+ isScaleLoading,
80277
+ deleteChildrenModalData,
80278
+ rerunModalData,
80279
+ isRerunLoading,
79763
80280
  handleActionClick,
79764
80281
  handleCloseModal,
79765
80282
  handleDeleteModalClose,
79766
80283
  handleEvictConfirm,
79767
- handleEvictCancel
80284
+ handleEvictCancel,
80285
+ handleScaleConfirm,
80286
+ handleScaleCancel,
80287
+ handleDeleteChildrenClose,
80288
+ handleRerunConfirm,
80289
+ handleRerunCancel
79768
80290
  } = useActionsDropdownHandlers({
79769
80291
  replaceValues,
79770
80292
  multiQueryData: safeMultiQueryData
@@ -79814,6 +80336,29 @@ Take a look at the reducer(s) handling this action type: ${action.type}.
79814
80336
  children: "This will evict the pod. It may be blocked by PodDisruptionBudget."
79815
80337
  }
79816
80338
  ),
80339
+ scaleModalData && /* @__PURE__ */ jsxRuntimeExports.jsx(
80340
+ ScaleModal,
80341
+ {
80342
+ open: true,
80343
+ currentReplicas: scaleModalData.currentReplicas,
80344
+ name: scaleModalData.name,
80345
+ onConfirm: handleScaleConfirm,
80346
+ onClose: handleScaleCancel,
80347
+ isLoading: isScaleLoading
80348
+ }
80349
+ ),
80350
+ deleteChildrenModalData && /* @__PURE__ */ jsxRuntimeExports.jsx(DeleteModalMany, { data: deleteChildrenModalData.children, onClose: handleDeleteChildrenClose }),
80351
+ rerunModalData && /* @__PURE__ */ jsxRuntimeExports.jsx(
80352
+ ConfirmModal,
80353
+ {
80354
+ title: `Rerun job "${rerunModalData.sourceName}"?`,
80355
+ onConfirm: handleRerunConfirm,
80356
+ onClose: handleRerunCancel,
80357
+ confirmText: "Rerun",
80358
+ confirmLoading: isRerunLoading,
80359
+ children: "This will create a new Job with the same spec."
80360
+ }
80361
+ ),
79817
80362
  children
79818
80363
  ] });
79819
80364
  };
@@ -84583,6 +85128,7 @@ Take a look at the reducer(s) handling this action type: ${action.type}.
84583
85128
  const [isLoading, setIsLoading] = React$1.useState(true);
84584
85129
  const [isNamespaced, setIsNamespaced] = React$1.useState(false);
84585
85130
  const [isError, setIsError] = React$1.useState(false);
85131
+ const hasAppliedBackendModeRef = React$1.useRef(false);
84586
85132
  const { data: overridesData, isLoading: overridesLoading } = useK8sSmartResource({
84587
85133
  cluster,
84588
85134
  apiGroup: forcingCustomization.baseApiGroup,
@@ -84601,20 +85147,20 @@ Take a look at the reducer(s) handling this action type: ${action.type}.
84601
85147
  )
84602
85148
  });
84603
85149
  const fallbackToManualMode = React$1.useCallback(() => {
84604
- if (modeData) {
84605
- modeData.onChange("Manual");
84606
- modeData.onDisabled();
84607
- }
85150
+ if (!modeData || hasAppliedBackendModeRef.current) return;
85151
+ modeData.onChange("Manual");
85152
+ hasAppliedBackendModeRef.current = true;
84608
85153
  }, [modeData]);
84609
85154
  const applyForceViewMode = React$1.useCallback(
84610
85155
  (forceViewMode) => {
84611
- if (!modeData || !forceViewMode) return;
85156
+ if (!modeData || !forceViewMode || hasAppliedBackendModeRef.current) return;
84612
85157
  if (forceViewMode === "Manual") {
84613
85158
  modeData.onChange("Manual");
84614
- modeData.onDisabled();
85159
+ hasAppliedBackendModeRef.current = true;
84615
85160
  return;
84616
85161
  }
84617
85162
  modeData.onChange("OpenAPI");
85163
+ hasAppliedBackendModeRef.current = true;
84618
85164
  },
84619
85165
  [modeData]
84620
85166
  );
@@ -85120,8 +85666,8 @@ Take a look at the reducer(s) handling this action type: ${action.type}.
85120
85666
  namespace,
85121
85667
  apiGroup,
85122
85668
  apiVersion: apiVersion || "",
85123
- plural: type,
85124
- isEnabled: Boolean(apiVersion && addedMode && type !== "direct")
85669
+ plural: plural || "",
85670
+ isEnabled: Boolean(apiVersion && plural && addedMode && type !== "direct")
85125
85671
  });
85126
85672
  const isAddedMode = Boolean(addedMode);
85127
85673
  const isDirectType = type === "direct";
@@ -89239,7 +89785,13 @@ Take a look at the reducer(s) handling this action type: ${action.type}.
89239
89785
  queryKey: ["usePluginManifest", cluster],
89240
89786
  queryFn: () => getPlugins({ cluster }),
89241
89787
  refetchInterval: refetchInterval !== void 0 ? refetchInterval : 6e4,
89242
- enabled: isEnabled
89788
+ enabled: isEnabled,
89789
+ // 🔴 Disable ALL auto refetching
89790
+ refetchOnWindowFocus: false,
89791
+ refetchOnReconnect: false,
89792
+ refetchOnMount: false,
89793
+ // 🟢 Optional: Make data never go stale
89794
+ staleTime: Infinity
89243
89795
  });
89244
89796
  };
89245
89797