foreman_remote_execution 16.1.0 → 16.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/foreman_remote_execution/locale/de/foreman_remote_execution.js +54 -30
  3. data/app/assets/javascripts/foreman_remote_execution/locale/en_GB/foreman_remote_execution.js +52 -28
  4. data/app/assets/javascripts/foreman_remote_execution/locale/es/foreman_remote_execution.js +55 -31
  5. data/app/assets/javascripts/foreman_remote_execution/locale/fr/foreman_remote_execution.js +61 -37
  6. data/app/assets/javascripts/foreman_remote_execution/locale/ja/foreman_remote_execution.js +62 -38
  7. data/app/assets/javascripts/foreman_remote_execution/locale/ka/foreman_remote_execution.js +53 -29
  8. data/app/assets/javascripts/foreman_remote_execution/locale/ko/foreman_remote_execution.js +61 -37
  9. data/app/assets/javascripts/foreman_remote_execution/locale/pt_BR/foreman_remote_execution.js +55 -31
  10. data/app/assets/javascripts/foreman_remote_execution/locale/ru/foreman_remote_execution.js +52 -28
  11. data/app/assets/javascripts/foreman_remote_execution/locale/zh_CN/foreman_remote_execution.js +61 -37
  12. data/app/assets/javascripts/foreman_remote_execution/locale/zh_TW/foreman_remote_execution.js +52 -28
  13. data/app/views/api/v2/job_templates/main.json.rabl +1 -1
  14. data/lib/foreman_remote_execution/plugin.rb +1 -1
  15. data/lib/foreman_remote_execution/version.rb +1 -1
  16. data/locale/de/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  17. data/locale/de/foreman_remote_execution.po +54 -30
  18. data/locale/en_GB/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  19. data/locale/en_GB/foreman_remote_execution.po +52 -28
  20. data/locale/es/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  21. data/locale/es/foreman_remote_execution.po +55 -31
  22. data/locale/foreman_remote_execution.pot +193 -156
  23. data/locale/fr/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  24. data/locale/fr/foreman_remote_execution.po +61 -37
  25. data/locale/ja/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  26. data/locale/ja/foreman_remote_execution.po +62 -38
  27. data/locale/ka/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  28. data/locale/ka/foreman_remote_execution.po +53 -29
  29. data/locale/ko/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  30. data/locale/ko/foreman_remote_execution.po +61 -37
  31. data/locale/pt_BR/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  32. data/locale/pt_BR/foreman_remote_execution.po +55 -31
  33. data/locale/ru/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  34. data/locale/ru/foreman_remote_execution.po +52 -28
  35. data/locale/zh_CN/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  36. data/locale/zh_CN/foreman_remote_execution.po +61 -37
  37. data/locale/zh_TW/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  38. data/locale/zh_TW/foreman_remote_execution.po +52 -28
  39. data/webpack/JobInvocationDetail/CheckboxesActions.js +1 -2
  40. data/webpack/JobInvocationDetail/JobInvocationHostTable.js +14 -1
  41. data/webpack/JobInvocationDetail/TemplateInvocation.js +63 -50
  42. data/webpack/JobInvocationDetail/TemplateInvocationPage.js +1 -0
  43. data/webpack/JobInvocationDetail/__tests__/TableToolbarActions.test.js +1 -1
  44. data/webpack/JobInvocationDetail/__tests__/TemplateInvocation.test.js +4 -0
  45. data/webpack/JobInvocationDetail/index.js +1 -1
  46. data/webpack/react_app/components/HostKebab/KebabItems.js +2 -3
  47. metadata +2 -2
@@ -57,9 +57,9 @@ export const TemplateInvocation = ({
57
57
  hostID,
58
58
  jobID,
59
59
  isInTableView,
60
+ isExpanded,
60
61
  hostName,
61
62
  hostProxy,
62
- isExpanded,
63
63
  }) => {
64
64
  const intervalRef = useRef(null);
65
65
  const templateURL = showTemplateInvocationUrl(hostID, jobID);
@@ -67,72 +67,76 @@ export const TemplateInvocation = ({
67
67
 
68
68
  const status = useSelector(selectTemplateInvocationStatus(hostID));
69
69
  const response = useSelector(selectTemplateInvocation(hostID));
70
- const finished = response.finished ?? true;
71
- const autoRefresh = response.auto_refresh || false;
72
70
  const dispatch = useDispatch();
73
71
 
72
+ const responseRef = useRef(response);
74
73
  useEffect(() => {
75
- const getData = async () => {
76
- if (
77
- (!isInTableView || (isInTableView && isExpanded)) &&
78
- (Object.keys(response).length === 0 || autoRefresh)
79
- ) {
80
- dispatch(
81
- APIActions.get({
82
- url: templateURL,
83
- key: `${GET_TEMPLATE_INVOCATION}_${hostID}`,
84
- handleError: () => {
85
- if (intervalRef.current) clearInterval(intervalRef.current);
86
- },
87
- })
88
- );
89
- }
74
+ responseRef.current = response;
75
+ }, [response]);
76
+
77
+ const [showOutputType, setShowOutputType] = useState({
78
+ stderr: true,
79
+ stdout: true,
80
+ debug: true,
81
+ });
82
+ const [showTemplatePreview, setShowTemplatePreview] = useState(false);
83
+ const [showCommand, setShowCommand] = useState(false);
84
+
85
+ useEffect(() => {
86
+ const dispatchFetch = () => {
87
+ dispatch(
88
+ APIActions.get({
89
+ url: templateURL,
90
+ key: `${GET_TEMPLATE_INVOCATION}_${hostID}`,
91
+ })
92
+ );
90
93
  };
91
- getData();
92
- if (!finished && autoRefresh) {
94
+
95
+ if (intervalRef.current) {
96
+ clearInterval(intervalRef.current);
97
+ intervalRef.current = null;
98
+ }
99
+
100
+ if (isExpanded) {
101
+ if (isEmpty(responseRef.current)) {
102
+ dispatchFetch();
103
+ }
104
+
93
105
  intervalRef.current = setInterval(() => {
94
- getData();
106
+ const latestResponse = responseRef.current;
107
+ const finished = latestResponse?.finished ?? true;
108
+ // eslint-disable-next-line camelcase
109
+ const autoRefresh = latestResponse?.auto_refresh || false;
110
+
111
+ if (!finished && autoRefresh) {
112
+ dispatchFetch();
113
+ } else if (intervalRef.current) {
114
+ clearInterval(intervalRef.current);
115
+ }
95
116
  }, 5000);
96
117
  }
97
118
 
98
119
  return () => {
99
120
  if (intervalRef.current) {
100
121
  clearInterval(intervalRef.current);
101
- intervalRef.current = null;
102
122
  }
103
123
  };
104
- }, [
105
- dispatch,
106
- templateURL,
107
- isExpanded,
108
- isInTableView,
109
- finished,
110
- autoRefresh,
111
- hostID,
112
- ]);
124
+ }, [isExpanded, dispatch, templateURL, hostID]);
125
+
126
+ if (!isExpanded) {
127
+ return null;
128
+ }
129
+
130
+ if ((status === STATUS.PENDING && isEmpty(response)) || !response) {
131
+ return <Skeleton />;
132
+ }
113
133
 
114
134
  const errorMessage =
115
135
  response?.response?.data?.error?.message ||
116
136
  response?.response?.data?.error ||
117
137
  JSON.stringify(response);
118
- const {
119
- preview,
120
- output,
121
- input_values: inputValues,
122
- task,
123
- permissions,
124
- } = response;
125
- const { id: taskID, cancellable: taskCancellable } = task || {};
126
- const [showOutputType, setShowOutputType] = useState({
127
- stderr: true,
128
- stdout: true,
129
- debug: true,
130
- });
131
- const [showTemplatePreview, setShowTemplatePreview] = useState(false);
132
- const [showCommand, setCommand] = useState(false);
133
- if (status === STATUS.PENDING && isEmpty(response)) {
134
- return <Skeleton />;
135
- } else if (status === STATUS.ERROR) {
138
+
139
+ if (status === STATUS.ERROR) {
136
140
  return (
137
141
  <Alert
138
142
  ouiaId="template-invocation-error-alert"
@@ -146,6 +150,15 @@ export const TemplateInvocation = ({
146
150
  );
147
151
  }
148
152
 
153
+ const {
154
+ preview,
155
+ output,
156
+ input_values: inputValues,
157
+ task,
158
+ permissions,
159
+ } = response;
160
+ const { id: taskID, cancellable: taskCancellable } = task || {};
161
+
149
162
  return (
150
163
  <div
151
164
  id={`template-invocation-${hostID}`}
@@ -159,7 +172,7 @@ export const TemplateInvocation = ({
159
172
  setShowTemplatePreview={setShowTemplatePreview}
160
173
  showTemplatePreview={showTemplatePreview}
161
174
  showCommand={showCommand}
162
- setShowCommand={setCommand}
175
+ setShowCommand={setShowCommand}
163
176
  newTabUrl={templateInvocationPageUrl(hostID, jobID)}
164
177
  isInTableView={isInTableView}
165
178
  copyToClipboard={
@@ -36,6 +36,7 @@ const TemplateInvocationPage = ({
36
36
  hostID={hostID}
37
37
  jobID={jobID}
38
38
  isInTableView={false}
39
+ isExpanded
39
40
  hostName={hostName}
40
41
  hostProxy={hostProxy}
41
42
  />
@@ -196,7 +196,7 @@ describe('TableToolbarActions', () => {
196
196
  const rerunLink = screen.getByRole('link', { name: /rerun/i });
197
197
  expect(rerunLink).toBeEnabled();
198
198
  const expectedHref = foremanUrl(
199
- `/job_invocations/42/rerun?search=(name~*) AND ((id ^ (101, 102, 103)))`
199
+ `/job_invocations/42/rerun?search=(job_invocation.id = 42) AND ((id ^ (101, 102, 103)))`
200
200
  );
201
201
  expect(rerunLink).toHaveAttribute('href', expectedHref);
202
202
  });
@@ -32,6 +32,7 @@ describe('TemplateInvocation', () => {
32
32
  hostID="1"
33
33
  jobID="1"
34
34
  isInTableView={false}
35
+ isExpanded
35
36
  hostName="example-host"
36
37
  hostProxy={{ name: 'example-proxy', href: '#' }}
37
38
  />
@@ -54,6 +55,7 @@ describe('TemplateInvocation', () => {
54
55
  hostID="1"
55
56
  jobID="1"
56
57
  isInTableView={false}
58
+ isExpanded
57
59
  hostName="example-host"
58
60
  hostProxy={{ name: 'example-proxy', href: '#' }}
59
61
  />
@@ -108,6 +110,7 @@ describe('TemplateInvocation', () => {
108
110
  hostID="1"
109
111
  jobID="1"
110
112
  isInTableView={false}
113
+ isExpanded
111
114
  hostName="example-host"
112
115
  hostProxy={{ name: 'example-proxy', href: '#' }}
113
116
  />
@@ -133,6 +136,7 @@ describe('TemplateInvocation', () => {
133
136
  hostID="1"
134
137
  jobID="1"
135
138
  isInTableView={false}
139
+ isExpanded
136
140
  hostName="example-host"
137
141
  />
138
142
  </Provider>
@@ -183,9 +183,9 @@ const JobInvocationDetailPage = ({
183
183
  id={id}
184
184
  targeting={targeting}
185
185
  failedCount={failed}
186
- finished={finished}
187
186
  autoRefresh={autoRefresh}
188
187
  initialFilter={selectedFilter}
188
+ statusLabel={statusLabel}
189
189
  onFilterUpdate={handleFilterChange}
190
190
  />
191
191
  </SkeletonLoader>
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import { useSelector } from 'react-redux';
3
- import { DropdownItem } from '@patternfly/react-core/deprecated';
3
+ import { DropdownItem } from '@patternfly/react-core';
4
4
  import { CodeIcon } from '@patternfly/react-icons';
5
5
  import { selectAPIResponse } from 'foremanReact/redux/API/APISelectors';
6
6
  import { translate as __ } from 'foremanReact/common/I18n';
@@ -16,9 +16,8 @@ const HostKebabItems = () => {
16
16
  <DropdownItem
17
17
  ouiaId="web-console-dropdown-item"
18
18
  icon={<CodeIcon />}
19
- href={consoleUrl}
19
+ to={consoleUrl}
20
20
  target="_blank"
21
- rel="noreferrer"
22
21
  >
23
22
  {__('Web Console')}
24
23
  </DropdownItem>
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foreman_remote_execution
3
3
  version: !ruby/object:Gem::Version
4
- version: 16.1.0
4
+ version: 16.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Foreman Remote Execution team
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-08-05 00:00:00.000000000 Z
10
+ date: 2025-08-29 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: deface