foreman_patch 1.1.6.alpha5 → 1.2.0.alpha1

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 (126) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/foreman_patch/api/v2/invocations_controller.rb +1 -23
  3. data/app/controllers/foreman_patch/concerns/hosts_controller_extensions.rb +41 -35
  4. data/app/helpers/foreman_patch/hosts_helper.rb +1 -1
  5. data/app/lib/actions/foreman_patch/cycle/complete.rb +41 -0
  6. data/app/lib/actions/foreman_patch/cycle/create.rb +1 -5
  7. data/app/lib/actions/foreman_patch/cycle/initiate.rb +1 -5
  8. data/app/lib/actions/foreman_patch/cycle/plan.rb +66 -0
  9. data/app/lib/actions/foreman_patch/invocation/action.rb +29 -23
  10. data/app/lib/actions/foreman_patch/invocation/patch.rb +8 -16
  11. data/app/lib/actions/foreman_patch/invocation/wait_for_host.rb +29 -4
  12. data/app/lib/actions/foreman_patch/round/patch.rb +1 -5
  13. data/app/lib/actions/foreman_patch/round/plan.rb +33 -0
  14. data/app/lib/actions/foreman_patch/window/plan.rb +43 -0
  15. data/app/lib/actions/foreman_patch/window/publish.rb +1 -5
  16. data/app/lib/actions/foreman_patch/window/resolve_hosts.rb +1 -5
  17. data/app/models/foreman_patch/invocation.rb +4 -4
  18. data/app/models/foreman_patch/round.rb +23 -4
  19. data/app/models/setting/patching.rb +57 -0
  20. data/app/services/foreman_patch/ticket/api.rb +1 -2
  21. data/app/views/foreman_patch/api/v2/invocations/base.json.rabl +1 -1
  22. data/app/views/foreman_patch/api/v2/invocations/phase.json.rabl +7 -0
  23. data/app/views/foreman_patch/api/v2/invocations/show.json.rabl +2 -2
  24. data/app/views/foreman_patch/api/v2/rounds/base.json.rabl +1 -1
  25. data/app/views/foreman_patch/api/v2/rounds/status.json.rabl +8 -2
  26. data/app/views/foreman_patch/groups/index.html.erb +1 -1
  27. data/app/views/foreman_patch/invocations/show.html.erb +26 -1
  28. data/app/views/foreman_patch/layouts/react.html.erb +1 -1
  29. data/app/views/templates/ensure_services.erb +4 -7
  30. data/config/api_routes.rb +24 -28
  31. data/config/routes/mount_engine.rb +3 -0
  32. data/config/routes/overrides.rb +10 -0
  33. data/config/routes.rb +29 -40
  34. data/db/seeds.d/100-assign_features_with_templates.rb +12 -6
  35. data/lib/foreman_patch/engine.rb +46 -11
  36. data/lib/foreman_patch/plugin.rb +47 -0
  37. data/lib/foreman_patch/version.rb +1 -1
  38. data/lib/foreman_patch.rb +2 -3
  39. data/locale/en/foreman_patch.po +1 -1
  40. data/locale/foreman_patch.pot +1 -1
  41. data/locale/gemspec.rb +1 -1
  42. data/package.json +9 -20
  43. data/public/assets/foreman_patch/cycle_plans-e5667e178ba389908f5c815b24ec0ea77c340849d56bc39c5ce72bb626bd446a.scss +6 -0
  44. data/public/assets/foreman_patch/cycle_plans-e5667e178ba389908f5c815b24ec0ea77c340849d56bc39c5ce72bb626bd446a.scss.gz +0 -0
  45. data/public/assets/foreman_patch/cycle_plans-ff3d252119622a68828ff70f4a97328303963002237dbf850e92d6a706e93667.scss.gz +0 -0
  46. data/public/assets/foreman_patch/foreman_patch-be2e2ba89548f4a490612e8a6cd1cdebc0473be89f8023a3df7612f05a75d301.css.gz +0 -0
  47. data/public/assets/foreman_patch/foreman_patch-ce5805a60c0d5f896f557ff5246e5a09172043004c850b39bea54e618df1c485.css +1 -0
  48. data/public/assets/foreman_patch/foreman_patch-ce5805a60c0d5f896f557ff5246e5a09172043004c850b39bea54e618df1c485.css.gz +0 -0
  49. data/public/assets/foreman_patch/foreman_patch.json +1 -1
  50. data/public/assets/foreman_patch/plan_edit_windows-9ba20f84f3ecf2c4eb903acd57d30ee3e16f023a79db30bc614aa22f26442ce3.js.gz +0 -0
  51. data/public/assets/foreman_patch/plan_edit_windows-e656ba411642a7f983b51958ab30ac49c056322d19295a603cff4d5e6c71c8ed.js +1 -0
  52. data/public/assets/foreman_patch/plan_edit_windows-e656ba411642a7f983b51958ab30ac49c056322d19295a603cff4d5e6c71c8ed.js.gz +0 -0
  53. data/public/webpack/foreman_patch/bundle-e45c4bb530e40506f2da.js +6 -0
  54. data/public/webpack/foreman_patch/bundle-e45c4bb530e40506f2da.js.gz +0 -0
  55. data/public/webpack/foreman_patch/bundle-e45c4bb530e40506f2da.js.map +1 -0
  56. data/public/webpack/foreman_patch/bundle-e45c4bb530e40506f2da.js.map.gz +0 -0
  57. data/public/webpack/foreman_patch/{foreman_patch-8909c3e06f012a43f769.css → foreman_patch-4a4e1a59d74af09c4b8b.css} +1 -1
  58. data/public/webpack/foreman_patch/{foreman_patch-8909c3e06f012a43f769.css.gz → foreman_patch-4a4e1a59d74af09c4b8b.css.gz} +0 -0
  59. data/public/webpack/foreman_patch/foreman_patch-4a4e1a59d74af09c4b8b.js +6 -0
  60. data/public/webpack/foreman_patch/foreman_patch-4a4e1a59d74af09c4b8b.js.gz +0 -0
  61. data/public/webpack/foreman_patch/foreman_patch-4a4e1a59d74af09c4b8b.js.map +1 -0
  62. data/public/webpack/foreman_patch/foreman_patch-4a4e1a59d74af09c4b8b.js.map.gz +0 -0
  63. data/public/webpack/foreman_patch/manifest.json +8 -13
  64. data/public/webpack/foreman_patch/manifest.json.gz +0 -0
  65. data/public/webpack/foreman_patch/{vendor-769bd77f6be96c3c37e1.js → vendor-4b77c91f1e9103179596.js} +2 -2
  66. data/public/webpack/foreman_patch/vendor-4b77c91f1e9103179596.js.gz +0 -0
  67. data/public/webpack/foreman_patch/{vendor-769bd77f6be96c3c37e1.js.map → vendor-4b77c91f1e9103179596.js.map} +1 -1
  68. data/public/webpack/foreman_patch/vendor-4b77c91f1e9103179596.js.map.gz +0 -0
  69. data/webpack/components/Invocation/Invocation.js +47 -0
  70. data/webpack/{src/Components → components}/Invocation/InvocationSelectors.js +3 -0
  71. data/webpack/components/Invocation/index.js +36 -0
  72. data/webpack/components/Invocations/Invocations.js +16 -48
  73. data/webpack/components/Invocations/InvocationsPage.js +1 -24
  74. data/webpack/components/Invocations/InvocationsSelectors.js +1 -1
  75. data/webpack/components/Invocations/components/{InvocationActions.js → InvocationItem.js} +16 -4
  76. data/webpack/components/Invocations/index.js +12 -95
  77. data/webpack/components/RoundProgress/AggregateStatus.js +5 -6
  78. data/webpack/components/RoundProgress/RoundProgress.js +6 -7
  79. data/webpack/components/RoundProgress/RoundProgressSelectors.js +2 -3
  80. data/webpack/components/common/Calendar/Calendar.js +4 -5
  81. data/webpack/components/common/Terminal/OutputLine.js +26 -0
  82. data/webpack/components/common/Terminal/Terminal.js +115 -0
  83. data/webpack/components/common/Terminal/Terminal.scss +47 -0
  84. data/webpack/index.js +0 -3
  85. metadata +91 -54
  86. data/app/controllers/foreman_patch/react_controller.rb +0 -12
  87. data/app/lib/actions/foreman_patch/invocation/process_logging.rb +0 -44
  88. data/app/lib/actions/foreman_patch/invocation/proxy_action.rb +0 -52
  89. data/app/models/foreman_patch/event.rb +0 -13
  90. data/app/views/foreman_patch/api/v2/invocations/event.json.rabl +0 -3
  91. data/db/migrate/20230706092400_nullify_group_on_delete.rb +0 -11
  92. data/db/migrate/20230707102800_create_invocation_events.rb +0 -16
  93. data/lib/foreman_patch/register.rb +0 -119
  94. data/public/webpack/foreman_patch/bundle-831173d6ae39953b2409.js +0 -6
  95. data/public/webpack/foreman_patch/bundle-831173d6ae39953b2409.js.gz +0 -0
  96. data/public/webpack/foreman_patch/bundle-831173d6ae39953b2409.js.map +0 -1
  97. data/public/webpack/foreman_patch/bundle-831173d6ae39953b2409.js.map.gz +0 -0
  98. data/public/webpack/foreman_patch/foreman_patch-8909c3e06f012a43f769.js +0 -6
  99. data/public/webpack/foreman_patch/foreman_patch-8909c3e06f012a43f769.js.gz +0 -0
  100. data/public/webpack/foreman_patch/foreman_patch-8909c3e06f012a43f769.js.map +0 -1
  101. data/public/webpack/foreman_patch/foreman_patch-8909c3e06f012a43f769.js.map.gz +0 -0
  102. data/public/webpack/foreman_patch/foreman_patch:global-d71cc6e1e759f04f631a.css +0 -1
  103. data/public/webpack/foreman_patch/foreman_patch:global-d71cc6e1e759f04f631a.css.gz +0 -0
  104. data/public/webpack/foreman_patch/foreman_patch:global-d71cc6e1e759f04f631a.js +0 -6
  105. data/public/webpack/foreman_patch/foreman_patch:global-d71cc6e1e759f04f631a.js.gz +0 -0
  106. data/public/webpack/foreman_patch/foreman_patch:global-d71cc6e1e759f04f631a.js.map +0 -1
  107. data/public/webpack/foreman_patch/foreman_patch:global-d71cc6e1e759f04f631a.js.map.gz +0 -0
  108. data/public/webpack/foreman_patch/vendor-769bd77f6be96c3c37e1.js.gz +0 -0
  109. data/public/webpack/foreman_patch/vendor-769bd77f6be96c3c37e1.js.map.gz +0 -0
  110. data/webpack/components/common/Table/index.js +0 -28
  111. data/webpack/global_index.js +0 -16
  112. data/webpack/src/Components/Invocation/Invocation.js +0 -67
  113. data/webpack/src/Components/Invocation/InvocationLogFooter.js +0 -30
  114. data/webpack/src/Components/Invocation/InvocationLogToolbar.js +0 -80
  115. data/webpack/src/Components/Invocation/index.js +0 -62
  116. data/webpack/src/Components/InvocationStatus.js +0 -50
  117. data/webpack/src/Components/Loading.js +0 -51
  118. data/webpack/src/Extends/index.js +0 -15
  119. data/webpack/src/Router/routes.js +0 -5
  120. data/webpack/src/reducers.js +0 -7
  121. /data/public/webpack/foreman_patch/{bundle-831173d6ae39953b2409.css → bundle-e45c4bb530e40506f2da.css} +0 -0
  122. /data/public/webpack/foreman_patch/{bundle-831173d6ae39953b2409.css.gz → bundle-e45c4bb530e40506f2da.css.gz} +0 -0
  123. /data/webpack/{src/Components → components}/Invocation/InvocationActions.js +0 -0
  124. /data/webpack/{src/Components → components}/Invocation/InvocationConsts.js +0 -0
  125. /data/webpack/components/Invocations/{Invocations.css → InvocationsPage.scss} +0 -0
  126. /data/webpack/components/common/Calendar/{Calendar.css → Calendar.scss} +0 -0
@@ -0,0 +1,47 @@
1
+ import React, { useState } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { translate as __ } from 'foremanReact/common/I18n';
4
+ import { Tabs, Tab, TabTitleText, LoadingState } from 'patternfly-react';
5
+ import { STATUS } from 'foremanReact/constants';
6
+
7
+ import Terminal from '../common/Terminal/Terminal';
8
+
9
+ const Invocation = ({ invocation, status }) => {
10
+ if (status === STATUS.ERROR) {
11
+ return (
12
+ <Alert type="error">
13
+ {__(
14
+ 'There was an error loading the invocation, try refreshing the page.'
15
+ )}
16
+ </Alert>
17
+ );
18
+ }
19
+
20
+ const [activeTabKey, setActiveTabKey] = useState(0);
21
+
22
+ const handleTabClick = (event, tabIndex) => {
23
+ setActiveTabKey(tabIndex);
24
+ };
25
+
26
+ return (
27
+ <LoadingState loading={status == STATUS.PENDING}>
28
+ <Tabs activeKey={activeTabKey} onSelect={handleTabClick}>
29
+ <Tab eventKey={0} title={<TabTitleText>Overview</TabTitleText>}>
30
+ TODO: status
31
+ </Tab>
32
+ {invocation.phases.map((phase, index) => (
33
+ <Tab event={index + 1} title={<TabTitleText>{phase.humanized_name}</TabTitleText>}>
34
+ <Terminal key={phase.label} linesets={phase.live_output}/>
35
+ </Tab>
36
+ ))}
37
+ </Tabs>
38
+ </LoadingState>
39
+ );
40
+ };
41
+
42
+ Invocation.propTypes = {
43
+ status: PropTypes.string.isRequired,
44
+ invocation: PropTypes.object.isRequired,
45
+ };
46
+
47
+ export default Invocation;
@@ -7,5 +7,8 @@ import { INVOCATION } from './InvocationConsts';
7
7
  export const selectInvocation = state =>
8
8
  selectAPIResponse(state, INVOCATION) || {};
9
9
 
10
+ export const selectState = state =>
11
+ selectAPIResponse(state, INVOCATION).state;
12
+
10
13
  export const selectStatus = state =>
11
14
  selectAPIStatus(state, INVOCATION);
@@ -0,0 +1,36 @@
1
+ import React { useEffect, useState } from 'react';
2
+ import { useSelector, useDispatch } from 'react-redux';
3
+ import { stopInterval } from 'foremanReact/redux/middlewares/IntervalMiddleware';
4
+ import Invocation from './Invocation';
5
+ import {
6
+ selectInvocation,
7
+ selectState,
8
+ selectStatus,
9
+ } from './InvocationSelectors';
10
+ import { getData } from './InvocationActions';
11
+ import { INVOCATION } from './InvocationsConsts';
12
+
13
+ const WrappedInvocation = () => {
14
+ const dispatch = useDispatch();
15
+ const state = useSelector(selectState);
16
+ const invocation = useSelector(selectInvocation);
17
+ const status = useSelector(selectStatus);
18
+
19
+ useEffect(() => {
20
+ dispatch(getData());
21
+
22
+ return () => {
23
+ dispatch(stopInterval(INVOCATION));
24
+ };
25
+ }, [dispatch]);
26
+
27
+ useEffect(() => {
28
+ if (state === 'stopped') {
29
+ dispatch(stopInterval(INVOCATION));
30
+ }
31
+ }, [state, dispatch]);
32
+
33
+ return <Invocation invocation={invocation} status={status}/>
34
+ };
35
+
36
+ export default WrappedInvocation;
@@ -2,13 +2,11 @@ import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import { translate as __ } from 'foremanReact/common/I18n';
4
4
  import { LoadingState, Alert } from 'patternfly-react';
5
- import { TableComposable, Thead, Tr, Th, Tbody, Td } from '@patternfly/react-table';
6
5
  import { STATUS } from 'foremanReact/constants';
7
6
 
8
- import InvocationStatus from './components/InvocationStatus';
9
- import InvocationActions from './components/InvocationActions';
7
+ import InvocationItem from './components/InvocationItem';
10
8
 
11
- const Invocations = ({ status, items, selectAll, areAllSelected, onSelect, isSelected }) => {
9
+ const Invocations = ({ status, items }) => {
12
10
  if (status === STATUS.ERROR) {
13
11
  return (
14
12
  <Alert type="error">
@@ -20,51 +18,26 @@ const Invocations = ({ status, items, selectAll, areAllSelected, onSelect, isSel
20
18
  }
21
19
 
22
20
  const rows = items.length ? (
23
- items.map((item, rowIndex) => (
24
- <Tr key={`invocation-${item.id}`}>
25
- <Td
26
- select={{
27
- rowIndex,
28
- onSelect: (_event, isSelecting) => onSelect(item, rowIndex, isSelecting),
29
- isSelected: isSelected(item)
30
- }}
31
- />
32
- <Td className="invocation_name">
33
- <a href={`/foreman_patch/invocations/${item.id}`}>{item.name}</a>
34
- </Td>
35
- <Td>
36
- <InvocationStatus status={item.status}/>
37
- </Td>
38
- <Td>
39
- <InvocationActions {...item}/>
40
- </Td>
41
- </Tr>
42
- ))
21
+ items.map(item => (<InvocationItem {...item} />))
43
22
  ) : (
44
- <Tr>
45
- <Td colSpan="4">{__('No hosts found.')}</Td>
46
- </Tr>
23
+ <tr>
24
+ <td colSpan="3">{__('No hosts found.')}</td>
25
+ </tr>
47
26
  );
48
27
 
49
28
  return (
50
29
  <LoadingState loading={!items.length && status === STATUS.PENDING}>
51
30
  <div>
52
- <TableComposable className="table table-bordered table-striped table-hover">
53
- <Thead>
54
- <Tr>
55
- <Th
56
- select={{
57
- onSelect: (_event, isSelecting) => selectAll(isSelecting),
58
- isSelected: areAllSelected
59
- }}
60
- />
61
- <Th>{__('Host')}</Th>
62
- <Th className="col-md-2">{__('Status')}</Th>
63
- <Th className="col-md-1">{__('Actions')}</Th>
64
- </Tr>
65
- </Thead>
66
- <Tbody>{rows}</Tbody>
67
- </TableComposable>
31
+ <table className="table table-bordered table-striped table-hover">
32
+ <thead>
33
+ <tr>
34
+ <th>{__('Host')}</th>
35
+ <th className="col-md-2">{__('Status')}</th>
36
+ <th className="col-md-1">{__('Actions')}</th>
37
+ </tr>
38
+ </thead>
39
+ <tbody>{rows}</tbody>
40
+ </table>
68
41
  </div>
69
42
  </LoadingState>
70
43
  );
@@ -73,15 +46,10 @@ const Invocations = ({ status, items, selectAll, areAllSelected, onSelect, isSel
73
46
  Invocations.propTypes = {
74
47
  status: PropTypes.string,
75
48
  items: PropTypes.array.isRequired,
76
- selectAll: PropTypes.func.isRequired,
77
- areAllSelected: PropTypes.bool,
78
- onSelect: PropTypes.func.isRequired,
79
- isSelected: PropTypes.func.isRequired,
80
49
  };
81
50
 
82
51
  Invocations.defaultProps = {
83
52
  status: null,
84
- areAllSelected: false,
85
53
  };
86
54
 
87
55
  export default Invocations;
@@ -4,7 +4,6 @@ import { Grid } from 'patternfly-react';
4
4
 
5
5
  import SearchBar from 'foremanReact/components/SearchBar';
6
6
  import Pagination from 'foremanReact/components/Pagination/PaginationWrapper';
7
- import { ActionButtons } from 'foremanReact/components/common/ActionButtons/ActionButtons';
8
7
  import { getControllerSearchProps } from 'foremanReact/constants';
9
8
 
10
9
  import Invocations from './Invocations';
@@ -18,11 +17,6 @@ const InvocationsPage = ({
18
17
  pagination,
19
18
  handleSearch,
20
19
  handlePagination,
21
- selectAll,
22
- areAllSelected,
23
- onSelect,
24
- isSelected,
25
- actions
26
20
  }) => (
27
21
  <div id="patch_invocations">
28
22
  <Grid.Row>
@@ -41,19 +35,9 @@ const InvocationsPage = ({
41
35
  }}
42
36
  />
43
37
  </Grid.Col>
44
- <Grid.Col md={6} className="title_action">
45
- <ActionButtons buttons={[]} />
46
- </Grid.Col>
47
38
  </Grid.Row>
48
39
  <br />
49
- <Invocations
50
- status={status}
51
- items={items}
52
- selectAll={selectAll}
53
- areAllSelected={areAllSelected}
54
- onSelect={onSelect}
55
- isSelected={isSelected}
56
- />
40
+ <Invocations status={status} items={items} />
57
41
  <Pagination
58
42
  viewType="table"
59
43
  itemCount={total}
@@ -73,17 +57,10 @@ InvocationsPage.propTypes = {
73
57
  pagination: PropTypes.object.isRequired,
74
58
  handleSearch: PropTypes.func.isRequired,
75
59
  handlePagination: PropTypes.func.isRequired,
76
- selectAll: PropTypes.func.isRequired,
77
- areAllSelected: PropTypes.bool,
78
- onSelect: PropTypes.func.isRequired,
79
- isSelected: PropTypes.func.isRequired,
80
- actions: PropTypes.array,
81
60
  };
82
61
 
83
62
  InvocationsPage.defaultProps = {
84
63
  status: null,
85
- areAllSelected: false,
86
- actions: []
87
64
  };
88
65
 
89
66
  export default InvocationsPage;
@@ -12,7 +12,7 @@ export const selectTotal = state =>
12
12
  selectAPIResponse(state, INVOCATIONS).total || 0;
13
13
 
14
14
  export const selectAutoRefresh = state =>
15
- selectItems(state).some(item => (item.status === 'pending' || item.status === 'planned'));
15
+ selectItems(state).some(item => (item.result === 'pending'));
16
16
 
17
17
  export const selectStatus = state => selectAPIStatus(state, INVOCATIONS);
18
18
 
@@ -3,7 +3,9 @@ import PropTypes from 'prop-types';
3
3
  import { ActionButtons } from 'foremanReact/components/common/ActionButtons/ActionButtons';
4
4
  import { translate as __ } from 'foremanReact/common/I18n';
5
5
 
6
- const InvocationActions = ({ id, name, status, task_id, host_id }) => {
6
+ import InvocationStatus from './InvocationStatus';
7
+
8
+ const InvocationItem = ({ id, name, status, task_id, host_id }) => {
7
9
 
8
10
  const actions = [
9
11
  {
@@ -39,11 +41,21 @@ const InvocationActions = ({ id, name, status, task_id, host_id }) => {
39
41
  }
40
42
 
41
43
  return (
42
- <ActionButtons buttons={[...actions]} />
44
+ <tr id={`invocation-${id}`}>
45
+ <td className="invocation_name">
46
+ <a href={`/foreman_patch/invocations/${id}`}>{name}</a>
47
+ </td>
48
+ <td className="invocation_status">
49
+ <InvocationStatus status={status} />
50
+ </td>
51
+ <td className="invocation_actions">
52
+ <ActionButtons buttons={[...actions]} />
53
+ </td>
54
+ </tr>
43
55
  );
44
56
  };
45
57
 
46
- InvocationActions.propTypes = {
58
+ InvocationItem.propTypes = {
47
59
  id: PropTypes.number.isRequired,
48
60
  name: PropTypes.string.isRequired,
49
61
  status: PropTypes.string.isRequired,
@@ -51,4 +63,4 @@ InvocationActions.propTypes = {
51
63
  task_id: PropTypes.number.isRequired,
52
64
  };
53
65
 
54
- export default InvocationActions;
66
+ export default InvocationItem;
@@ -1,21 +1,14 @@
1
1
  import React, { useEffect, useState } from 'react';
2
2
  import { useSelector, useDispatch } from 'react-redux';
3
3
  import PropTypes from 'prop-types';
4
- import { Grid } from 'patternfly-react';
5
4
 
6
- import {
5
+ import {
7
6
  withInterval,
8
7
  stopInterval
9
8
  } from 'foremanReact/redux/middlewares/IntervalMiddleware';
10
9
  import { get } from 'foremanReact/redux/API';
11
10
  import { useForemanSettings } from 'foremanReact/Root/Context/ForemanContext';
12
- import { getControllerSearchProps } from 'foremanReact/constants';
13
- import { translate as __ } from 'foremanReact/common/I18n';
14
- import SearchBar from 'foremanReact/components/SearchBar';
15
- import Pagination from 'foremanReact/components/Pagination/PaginationWrapper';
16
- import { ActionButtons } from 'foremanReact/components/common/ActionButtons/ActionButtons';
17
11
 
18
- import Invocations from './Invocations';
19
12
  import {
20
13
  selectItems,
21
14
  selectTotal,
@@ -25,8 +18,7 @@ import {
25
18
  } from './InvocationsSelectors';
26
19
  import { getUrl } from './InvocationsHelpers';
27
20
  import { INVOCATIONS } from './InvocationsConstants';
28
-
29
- import './Invocations.css';
21
+ import InvocationsPage from './InvocationsPage';
30
22
 
31
23
  const WrappedInvocations = ({ round }) => {
32
24
  const dispatch = useDispatch();
@@ -44,9 +36,6 @@ const WrappedInvocations = ({ round }) => {
44
36
  });
45
37
  const [url, setUrl] = useState(getUrl(round, searchQuery, pagination));
46
38
  const intervalExists = useSelector(selectIntervalExists);
47
- const [selectedItems, setSelectedItems] = useState([]);
48
- const [recentSelectedItemIndex, setRecentSelectedRowIndex] = useState(null);
49
- const [shifting, setShifting] = useState(false);
50
39
 
51
40
  const handleSearch = query => {
52
41
  const defaultPagination = { page: 1, perPage: pagination.perPage };
@@ -63,39 +52,13 @@ const WrappedInvocations = ({ round }) => {
63
52
  setUrl(getUrl(round, searchQuery, args));
64
53
  };
65
54
 
66
- const selectAll = (isSelecting) => setSelectedItems(isSelecting ? items.map(item => item.id) : []);
67
-
68
- const areAllSelected = selectedItems.length == items.length;
69
-
70
- const setItemSelected = (item, isSelecting) =>
71
- setSelectedItems(prevSelected => {
72
- const otherSelectedItems = prevSelected.filter(i => i !== item.id);
73
- return isSelecting ? [...otherSelectedItems, item.id] : otherSelectedItems;
74
- });
75
-
76
- const onSelect = (item, rowIndex, isSelecting) => {
77
- if (shifting && recentSelectedRowIndex !== null) {
78
- const numberSelected = rowIndex - recentSelectedRowIndex;
79
- const intermediateIndexes =
80
- numberSelected > 0
81
- ? Array.from(new Array(numberSelected + 1), (_x, i) => i + recentSelectedRowIndex)
82
- : Array.from(new Array(Math.abs(numberSelected) + 1), (_x, i) => i + rowIndex);
83
- intermediateIndexes.forEach(index, setItemSelected(items[index], isSelecting));
84
- } else {
85
- setItemSelected(item, isSelecting);
86
- }
87
- setRecentSelectedRowIndex(rowIndex);
88
- };
89
-
90
- const isSelected = item => selectedItems.includes(item.id);
91
-
92
55
  const stopApiInterval = () => {
93
56
  if (intervalExists) {
94
57
  dispatch(stopInterval(INVOCATIONS));
95
58
  }
96
59
  };
97
60
 
98
- const getData = url => withInterval(get({
61
+ const getData = url => withInterval(get({
99
62
  key: INVOCATIONS,
100
63
  url,
101
64
  handleError: () => {
@@ -104,73 +67,27 @@ const WrappedInvocations = ({ round }) => {
104
67
  }), 5000);
105
68
 
106
69
  useEffect(() => {
107
- const onKeyDown = (e) => {
108
- if (e.key === 'Shift') {
109
- setShifting(true);
110
- }
111
- };
112
- const onKeyUp = (e) => {
113
- if (e.key === 'Shift') {
114
- setShifting(false);
115
- }
116
- };
117
-
118
70
  dispatch(getData(url));
119
71
 
120
72
  if (!autoRefresh) {
121
73
  dispatch(stopInterval(INVOCATIONS));
122
74
  }
123
75
 
124
- document.addEventListener('keydown', onKeyDown);
125
- document.addEventListener('keyup', onKeyUp);
126
-
127
76
  return () => {
128
77
  dispatch(stopInterval(INVOCATIONS));
129
- document.removeEventListener('keydown', onKeyDown);
130
- document.removeEventListener('keyup', onKeyUp);
131
78
  };
132
79
  }, [dispatch, url, autoRefresh]);
133
80
 
134
81
  return (
135
- <React.Fragment>
136
- <Grid.Row>
137
- <Grid.Col md={6} className="title_filter">
138
- <SearchBar
139
- onSearch={handleSearch}
140
- data={{
141
- ...getControllerSearchProps('foreman_patch/invocations'),
142
- autocomplete: {
143
- id: 'invocations_search',
144
- searchQuery,
145
- url: '/foreman_patch/invocations/auto_complete_search',
146
- useKeyShortcuts: true,
147
- },
148
- bookmarks: {},
149
- }}
150
- />
151
- </Grid.Col>
152
- <Grid.Col md={6}>
153
- <ActionButtons buttons={actions} />
154
- </Grid.Col>
155
- </Grid.Row>
156
- <br />
157
- <Invocations
158
- status={status}
159
- items={items}
160
- selectAll={selectAll}
161
- areAllSelected={areAllSelected}
162
- isSelected={isSelected}
163
- onSelect={onSelect}
164
- />
165
- <Pagination
166
- viewType="table"
167
- itemCount={total}
168
- pagination={pagination}
169
- onChange={handlePagination}
170
- dropdownButtonId="invocations-pagination-dropdown"
171
- className="invocations-pagination"
172
- />
173
- </React.Fragment>
82
+ <InvocationsPage
83
+ status={status}
84
+ items={items}
85
+ total={total}
86
+ searchQuery={searchQuery}
87
+ handleSearch={handleSearch}
88
+ pagination={pagination}
89
+ handlePagination={handlePagination}
90
+ />
174
91
  );
175
92
  };
176
93
 
@@ -19,7 +19,7 @@ const AggregateStatus = ({ progress }) => (
19
19
  <span className="card-pf-aggregate-status-notification">
20
20
  <span id="failed_count">
21
21
  <span className="pficon pficon-error-circle-o" />
22
- {progress.error}
22
+ {progress.failed}
23
23
  </span>
24
24
  </span>
25
25
  <span className="card-pf-aggregate-status-notification">
@@ -31,7 +31,7 @@ const AggregateStatus = ({ progress }) => (
31
31
  <span className="card-pf-aggregate-status-notification">
32
32
  <span id="pending_count">
33
33
  <span className="pficon pficon-pending" />
34
- {progress.pending + progress.planned}
34
+ {progress.pending}
35
35
  </span>
36
36
  </span>
37
37
  <span className="card-pf-aggregate-status-notification">
@@ -46,12 +46,11 @@ const AggregateStatus = ({ progress }) => (
46
46
 
47
47
  AggregateStatus.propTypes = {
48
48
  progress: PropTypes.shape({
49
- planned: PropTypes.number,
50
- pending: PropTypes.number,
51
- running: PropTypes.number,
52
49
  success: PropTypes.number,
53
50
  warning: PropTypes.number,
54
- error: PropTypes.number,
51
+ failed: PropTypes.number,
52
+ running: PropTypes.number,
53
+ pending: PropTypes.number,
55
54
  cancelled: PropTypes.number,
56
55
  }).isRequired,
57
56
  };
@@ -11,14 +11,14 @@ const RoundProgress = ({ progress }) => {
11
11
  const data = [
12
12
  [__('Success'), progress.success, '#5CB85C'],
13
13
  [__('Warning'), progress.warning, '#DB843D'],
14
- [__('Failed'), progress.error, '#D9534F'],
14
+ [__('Failed'), progress.failed, '#D9534F'],
15
15
  [__('Running'), progress.running, '#3D96AE'],
16
- [__('Pending'), progress.pending + progress.planned, '#DEDEDE'],
16
+ [__('Pending'), progress.pending, '#DEDEDE'],
17
17
  [__('Cancelled'), progress.cancelled, '#B7312D'],
18
18
  ];
19
19
 
20
20
  const iMax = data.reduce((im, e, i, arr) =>
21
- (e[1] > arr[im][1] ? i : im), 0);
21
+ (e[1] > arr[im][i] ? i : im), 0);
22
22
 
23
23
  return (
24
24
  <div id="round_progress">
@@ -36,12 +36,11 @@ const RoundProgress = ({ progress }) => {
36
36
 
37
37
  RoundProgress.propTypes = {
38
38
  progress: PropTypes.shape({
39
- pending: PropTypes.number,
40
- planned: PropTypes.number,
41
- running: PropTypes.number,
42
39
  success: PropTypes.number,
43
40
  warning: PropTypes.number,
44
- error: PropTypes.number,
41
+ failed: PropTypes.number,
42
+ running: PropTypes.number,
43
+ pending: PropTypes.number,
45
44
  cancelled: PropTypes.number,
46
45
  }).isRequired,
47
46
  };
@@ -8,10 +8,9 @@ import { ROUND_PROGRESS } from './RoundProgressConstants';
8
8
  const defaultProgress = {
9
9
  success: 0,
10
10
  warning: 0,
11
- error: 0,
11
+ failed: 0,
12
12
  running: 0,
13
13
  pending: 0,
14
- planned: 0,
15
14
  cancelled: 0,
16
15
  };
17
16
 
@@ -19,7 +18,7 @@ export const selectProgress = state =>
19
18
  selectAPIResponse(state, ROUND_PROGRESS).progress || defaultProgress;
20
19
 
21
20
  export const selectAutoRefresh = state =>
22
- selectAPIResponse(state, ROUND_PROGRESS).status != 'complete';
21
+ !selectAPIResponse(state, ROUND_PROGRESS).complete;
23
22
 
24
23
  export const selectStatus = state =>
25
24
  selectAPIStatus(state, ROUND_PROGRESS);
@@ -2,13 +2,12 @@ import React, { useState } from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import { DndProvider } from 'react-dnd';
4
4
  import HTML5Backend from 'react-dnd-html5-backend';
5
-
6
- import './Calendar.css';
5
+ import './Calendar.scss';
7
6
 
8
7
  import { views, getView } from './View';
9
8
 
10
9
  const Calendar = (props) => {
11
- const { start, end, weekStartsOn, locale, onEventMoved } = props;
10
+ const {start, end, weekStartsOn, locale, onEventMoved} = props;
12
11
 
13
12
  const initialDate = () => {
14
13
  const { date } = props;
@@ -28,7 +27,7 @@ const Calendar = (props) => {
28
27
 
29
28
  const result = events.map(event => {
30
29
  if (event.id === updatedEvent.id) {
31
- return { ...event, ...updatedEvent };
30
+ return {...event, ...updatedEvent};
32
31
  }
33
32
  return event;
34
33
  });
@@ -79,7 +78,7 @@ Calendar.defaultProps = {
79
78
  date: new Date(),
80
79
  view: views.MONTH,
81
80
  events: [],
82
- onEventMoved: (event) => { },
81
+ onEventMoved: (event) => {},
83
82
  locale: 'en-US',
84
83
  weekStartsOn: 1,
85
84
  };
@@ -0,0 +1,26 @@
1
+ import React, { useState } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { classnames } from 'classname';
4
+
5
+ const OutputLine = ({index, type, children}) => {
6
+ return (
7
+ <div className={classnames('line', type)} >
8
+ <span className="counter">{index}</span>
9
+ <div className="content">
10
+ {children}
11
+ </div>
12
+ </div>
13
+ );
14
+ };
15
+
16
+ OutputLine.propTypes = {
17
+ index: PropTypes.number.isRequired,
18
+ type: PropTypes.string,
19
+ timestamp: PropTypes.number,
20
+ };
21
+
22
+ OutputLine.defaultProps = {
23
+ type: 'stdout',
24
+ };
25
+
26
+ export default OutputLine;