foreman_openscap 4.3.0 → 4.3.1

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 (49) hide show
  1. checksums.yaml +4 -4
  2. data/lib/foreman_openscap/version.rb +1 -1
  3. data/package.json +48 -0
  4. data/webpack/components/EmptyState.js +67 -0
  5. data/webpack/components/IndexLayout.js +35 -0
  6. data/webpack/components/IndexLayout.scss +3 -0
  7. data/webpack/components/IndexTable/IndexTableHelper.js +9 -0
  8. data/webpack/components/IndexTable/index.js +66 -0
  9. data/webpack/components/RuleSeverity/RuleSeverity.scss +3 -0
  10. data/webpack/components/RuleSeverity/RuleSeverity.test.js +13 -0
  11. data/webpack/components/RuleSeverity/__snapshots__/RuleSeverity.test.js.snap +41 -0
  12. data/webpack/components/RuleSeverity/i_severity-critical.svg +61 -0
  13. data/webpack/components/RuleSeverity/i_severity-high.svg +61 -0
  14. data/webpack/components/RuleSeverity/i_severity-low.svg +62 -0
  15. data/webpack/components/RuleSeverity/i_severity-med.svg +62 -0
  16. data/webpack/components/RuleSeverity/i_unknown.svg +33 -0
  17. data/webpack/components/RuleSeverity/index.js +33 -0
  18. data/webpack/components/withLoading.js +68 -0
  19. data/webpack/global_index.js +5 -0
  20. data/webpack/graphql/queries/cves.gql +18 -0
  21. data/webpack/graphql/queries/ovalContents.gql +11 -0
  22. data/webpack/graphql/queries/ovalPolicies.gql +12 -0
  23. data/webpack/graphql/queries/ovalPolicy.gql +21 -0
  24. data/webpack/helpers/commonHelper.js +1 -0
  25. data/webpack/helpers/globalIdHelper.js +13 -0
  26. data/webpack/helpers/pageParamsHelper.js +31 -0
  27. data/webpack/helpers/pathsHelper.js +22 -0
  28. data/webpack/helpers/tableHelper.js +9 -0
  29. data/webpack/index.js +8 -0
  30. data/webpack/routes/OvalContents/OvalContentsIndex/OvalContentsIndex.js +45 -0
  31. data/webpack/routes/OvalContents/OvalContentsIndex/OvalContentsTable.js +38 -0
  32. data/webpack/routes/OvalContents/OvalContentsIndex/__tests__/OvalContentsIndex.fixtures.js +106 -0
  33. data/webpack/routes/OvalContents/OvalContentsIndex/__tests__/OvalContentsIndex.test.js +75 -0
  34. data/webpack/routes/OvalContents/OvalContentsIndex/index.js +7 -0
  35. data/webpack/routes/OvalPolicies/OvalPoliciesIndex/OvalPoliciesIndex.js +46 -0
  36. data/webpack/routes/OvalPolicies/OvalPoliciesIndex/OvalPoliciesTable.js +44 -0
  37. data/webpack/routes/OvalPolicies/OvalPoliciesIndex/__tests__/OvalPoliciesIndex.fixtures.js +61 -0
  38. data/webpack/routes/OvalPolicies/OvalPoliciesIndex/__tests__/OvalPoliciesIndex.test.js +78 -0
  39. data/webpack/routes/OvalPolicies/OvalPoliciesIndex/index.js +7 -0
  40. data/webpack/routes/OvalPolicies/OvalPoliciesShow/CvesTab.js +48 -0
  41. data/webpack/routes/OvalPolicies/OvalPoliciesShow/CvesTable.js +63 -0
  42. data/webpack/routes/OvalPolicies/OvalPoliciesShow/OvalPoliciesShow.js +79 -0
  43. data/webpack/routes/OvalPolicies/OvalPoliciesShow/OvalPoliciesShowHelper.js +39 -0
  44. data/webpack/routes/OvalPolicies/OvalPoliciesShow/__tests__/OvalPoliciesShow.fixtures.js +78 -0
  45. data/webpack/routes/OvalPolicies/OvalPoliciesShow/__tests__/OvalPoliciesShow.test.js +112 -0
  46. data/webpack/routes/OvalPolicies/OvalPoliciesShow/index.js +35 -0
  47. data/webpack/routes/routes.js +28 -0
  48. data/webpack/testHelper.js +64 -0
  49. metadata +48 -2
@@ -0,0 +1,62 @@
1
+ <?xml version="1.0" encoding="UTF-8" standalone="no"?>
2
+ <!-- Generator: Adobe Illustrator 19.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
3
+
4
+ <svg
5
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
6
+ xmlns:cc="http://creativecommons.org/ns#"
7
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
8
+ xmlns:svg="http://www.w3.org/2000/svg"
9
+ xmlns="http://www.w3.org/2000/svg"
10
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
11
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
12
+ version="1.1"
13
+ id="Layer_1"
14
+ x="0px"
15
+ y="0px"
16
+ viewBox="0 0 146 166"
17
+ style="enable-background:new 0 0 146 166;"
18
+ xml:space="preserve"
19
+ sodipodi:docname="i_med.svg"
20
+ inkscape:version="0.92.1 r"><metadata
21
+ id="metadata7574"><rdf:RDF><cc:Work
22
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
23
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
24
+ id="defs7572" /><sodipodi:namedview
25
+ pagecolor="#ffffff"
26
+ bordercolor="#666666"
27
+ borderopacity="1"
28
+ objecttolerance="10"
29
+ gridtolerance="10"
30
+ guidetolerance="10"
31
+ inkscape:pageopacity="0"
32
+ inkscape:pageshadow="2"
33
+ inkscape:window-width="834"
34
+ inkscape:window-height="480"
35
+ id="namedview7570"
36
+ showgrid="false"
37
+ inkscape:zoom="1.4216867"
38
+ inkscape:cx="73"
39
+ inkscape:cy="83"
40
+ inkscape:window-x="0"
41
+ inkscape:window-y="1050"
42
+ inkscape:window-maximized="0"
43
+ inkscape:current-layer="Layer_1" /><style
44
+ type="text/css"
45
+ id="style7555">
46
+ .st0{fill:#808080;}
47
+ .st1{fill:#DEC800;}
48
+ .st2{fill:#CCCCCC;}
49
+ </style><g
50
+ id="g7559" /><path
51
+ class="st1"
52
+ d="M114.6,143.3H31c-7.2,0-13-4.8-13-10.6l0,0c0-5.9,5.9-10.6,13-10.6h83.6c7.2,0,13,4.8,13,10.6l0,0 C127.7,138.5,121.8,143.3,114.6,143.3z"
53
+ id="path7561" /><path
54
+ class="st1"
55
+ d="M114.6,110.2H31c-7.2,0-13-4.8-13-10.6l0,0C18,93.7,23.9,89,31,89h83.6c7.2,0,13,4.8,13,10.6l0,0 C127.7,105.4,121.8,110.2,114.6,110.2z"
56
+ id="path7563" /><path
57
+ class="st2"
58
+ d="M99.6,40.2H46c-4.6,0-8.4-3.1-8.4-6.8l0,0c0-3.8,3.8-6.9,8.4-6.9h53.7c4.6,0,8.4,3.1,8.4,6.8l0,0 C108.1,37.1,104.3,40.2,99.6,40.2z"
59
+ id="path7565" /><path
60
+ class="st2"
61
+ d="M99.6,73.3H46c-4.6,0-8.4-3.1-8.4-6.8l0,0c0-3.8,3.8-6.9,8.4-6.9h53.7c4.6,0,8.4,3.1,8.4,6.8l0,0 C108.1,70.2,104.3,73.3,99.6,73.3z"
62
+ id="path7567" /></svg>
@@ -0,0 +1,33 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <!-- Generator: Adobe Illustrator 19.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
3
+ <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
4
+ viewBox="0 0 110 130" style="enable-background:new 0 0 110 130;" xml:space="preserve">
5
+ <style type="text/css">
6
+ .st0{fill:#CCCCCC;}
7
+ .st1{fill:#FFFFFF;}
8
+ </style>
9
+ <path class="st0" d="M96.6,130H13c-7.2,0-13-5.9-13-13l0,0c0-7.2,5.9-13,13-13h83.6c7.2,0,13,5.9,13,13l0,0
10
+ C109.7,124.1,103.8,130,96.6,130z M96.6,95.4H13c-7.2,0-13-5.9-13-13l0,0c0-7.2,5.9-13,13-13h83.6c7.2,0,13,5.9,13,13l0,0
11
+ C109.7,89.5,103.8,95.4,96.6,95.4z M97,60.2H13.4c-7.2,0-13-5.9-13-13l0,0c0-7.2,5.9-13,13-13H97c7.2,0,13,5.9,13,13l0,0
12
+ C110,54.4,104.1,60.2,97,60.2z M96.6,26.1H13c-7.2,0-13-5.9-13-13l0,0C0,5.9,5.9,0,13,0h83.6c7.2,0,13,5.9,13,13l0,0
13
+ C109.7,20.2,103.8,26.1,96.6,26.1z"/>
14
+ <path class="st0" d="M53.3,123.4c-4.6,0-8.5-1.6-11.6-4.6c-3.2-3.1-4.8-7-4.8-11.5s1.6-8.4,4.8-11.5c1-1,2.1-1.8,3.3-2.5h-4.9v-8.7
15
+ c0-4.9,0.7-9.3,2.1-13.3c1.4-4,3.3-7.3,5.5-9.8c1.9-2.1,4.1-4.3,6.3-6.3c2.2-2,4.3-3.8,6.2-5.3c1.4-1.1,2.5-2.5,3.5-4.2
16
+ c0.9-1.6,1.3-3.2,1.3-5c0-2.7-0.8-4.7-2.5-6.3c-1.7-1.7-4.2-2.5-7.6-2.5c-4.2,0-7.3,1.2-9.4,3.5c-2.3,2.5-3.4,6.1-3.4,10.9V51H15.6
17
+ v-4.5c0-12.2,3.7-22,10.9-29.2c7.2-7.1,16.7-10.8,28.4-10.8c11.3,0,20.3,3.2,26.8,9.6c6.5,6.4,9.8,14.7,9.8,24.7
18
+ c0,4.4-0.7,8.5-2.2,12.1c-1.5,3.6-3.4,6.6-5.6,8.9c-1.9,1.9-3.9,3.8-6.1,5.9c-2.1,2-4.1,3.8-6,5.5c-1.4,1.2-2.6,2.9-3.6,4.9
19
+ c-1,2-1.4,4.2-1.4,6.7v8.5h-4.8c1.2,0.7,2.3,1.6,3.4,2.6c3.2,3.2,4.7,7,4.7,11.4c0,4.5-1.6,8.4-4.8,11.5
20
+ C61.8,121.9,57.9,123.4,53.3,123.4z"/>
21
+ <path class="st1" d="M54.8,11.1c10.1,0,18,2.8,23.6,8.3c5.6,5.6,8.4,12.7,8.4,21.5c0,3.9-0.6,7.4-1.9,10.4c-1.2,3.1-2.8,5.5-4.6,7.4
22
+ c-1.8,1.8-3.8,3.8-6,5.7c-2.1,2-4.1,3.8-6,5.4c-1.8,1.6-3.4,3.8-4.6,6.3c-1.2,2.6-1.9,5.5-1.9,8.6v4H44.6v-4.2
23
+ c0-4.4,0.6-8.3,1.9-11.8c1.2-3.5,2.8-6.2,4.6-8.3c1.8-2,3.8-4,6-6c2.1-1.9,4.1-3.6,6-5.1c1.8-1.4,3.4-3.3,4.6-5.5
24
+ c1.2-2.2,1.9-4.6,1.9-7.2c0-3.9-1.3-7.1-3.9-9.5c-2.6-2.5-6.2-3.7-10.7-3.7c-5.5,0-9.7,1.7-12.7,5c-3,3.3-4.5,8-4.5,13.9H20.1
25
+ c0-11,3.2-19.7,9.5-26C36,14.2,44.4,11.1,54.8,11.1 M53.3,95.7c3.4,0,6.2,1.1,8.5,3.4c2.3,2.3,3.4,5,3.4,8.2c0,3.3-1.1,6-3.4,8.3
26
+ c-2.3,2.2-5.1,3.4-8.5,3.4c-3.4,0-6.2-1.1-8.5-3.4c-2.3-2.2-3.4-5-3.4-8.3c0-3.3,1.1-6,3.4-8.3C47.1,96.8,50,95.7,53.3,95.7
27
+ M54.8,2.1C42,2.1,31.4,6.1,23.3,14.1c-8.1,8-12.2,18.9-12.2,32.4v9h9h17.4h9v-9c0-3.6,0.7-6.3,2.2-7.9c0.8-0.9,2.3-2.1,6.1-2.1
28
+ c2.1,0,3.7,0.4,4.5,1.2c0.5,0.5,1.1,1.2,1.1,3c0,1.1-0.2,2-0.7,2.9c-0.7,1.2-1.4,2.1-2.3,2.8c-2,1.6-4.2,3.4-6.5,5.5
29
+ c-2.3,2.1-4.6,4.3-6.6,6.6c-2.6,2.9-4.8,6.7-6.4,11.3c-1.6,4.4-2.4,9.4-2.4,14.8v4.2v7.5c-2.1,3.2-3.1,7-3.1,11
30
+ c0,5.7,2.1,10.8,6.1,14.7c4,3.9,9.1,5.9,14.8,5.9c5.7,0,10.8-2,14.8-5.9c4-3.9,6.1-9,6.1-14.7c0-4.1-1.1-7.9-3.3-11.1v-7.3v-4
31
+ c0-1.8,0.3-3.4,1-4.7c0.7-1.5,1.6-2.7,2.5-3.5c1.9-1.7,4-3.6,6.1-5.6c2.2-2,4.3-4,6.2-6c2.7-2.7,4.9-6.2,6.6-10.4
32
+ c1.7-4.1,2.5-8.8,2.5-13.8c0-11.2-3.7-20.6-11.1-27.8C77.5,5.7,67.4,2.1,54.8,2.1L54.8,2.1z"/>
33
+ </svg>
@@ -0,0 +1,33 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+
4
+ import SeverityCritical from './i_severity-critical.svg';
5
+ import SeverityHigh from './i_severity-high.svg';
6
+ import SeverityMedium from './i_severity-med.svg';
7
+ import SeverityLow from './i_severity-low.svg';
8
+ import SeverityUnknown from './i_unknown.svg';
9
+
10
+ import './RuleSeverity.scss';
11
+
12
+ const RuleSeverity = props => {
13
+ const propsMapping = {
14
+ low: { alt: 'Low Serverity', src: SeverityLow },
15
+ medium: { alt: 'Medium Serverity', src: SeverityMedium },
16
+ high: { alt: 'High Serverity', src: SeverityHigh },
17
+ critical: {
18
+ alt: 'Critical Serverity',
19
+ src: SeverityCritical,
20
+ },
21
+ unknown: { alt: 'Unknown Serverity', src: SeverityUnknown },
22
+ };
23
+
24
+ const imgProps = propsMapping[props.severity] || propsMapping.unknown;
25
+ // eslint-disable-next-line jsx-a11y/alt-text
26
+ return <img {...imgProps} className="severity-img" />;
27
+ };
28
+
29
+ RuleSeverity.propTypes = {
30
+ severity: PropTypes.string.isRequired,
31
+ };
32
+
33
+ export default RuleSeverity;
@@ -0,0 +1,68 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { translate as __ } from 'foremanReact/common/I18n';
4
+
5
+ import Loading from 'foremanReact/components/Loading';
6
+ import EmptyState from './EmptyState';
7
+
8
+ const errorStateTitle = __('Error!');
9
+ const emptyStateBody = '';
10
+
11
+ const pluckData = (data, path) => {
12
+ const split = path.split('.');
13
+ return split.reduce((memo, item) => {
14
+ if (item) {
15
+ return memo[item];
16
+ }
17
+ throw new Error('Unexpected empty segment in response data path');
18
+ }, data);
19
+ };
20
+
21
+ const withLoading = Component => {
22
+ const Subcomponent = ({
23
+ fetchFn,
24
+ resultPath,
25
+ renameData,
26
+ emptyStateTitle,
27
+ ...rest
28
+ }) => {
29
+ const { loading, error, data } = fetchFn(rest);
30
+
31
+ if (loading) {
32
+ return <Loading />;
33
+ }
34
+
35
+ if (error) {
36
+ return (
37
+ <EmptyState
38
+ error={error}
39
+ title={errorStateTitle}
40
+ body={error.message}
41
+ />
42
+ );
43
+ }
44
+
45
+ const result = pluckData(data, resultPath);
46
+
47
+ if ((Array.isArray(result) && result.length === 0) || !result) {
48
+ return <EmptyState title={emptyStateTitle} body={emptyStateBody} />;
49
+ }
50
+
51
+ return <Component {...rest} {...renameData(data)} />;
52
+ };
53
+
54
+ Subcomponent.propTypes = {
55
+ fetchFn: PropTypes.func.isRequired,
56
+ resultPath: PropTypes.string.isRequired,
57
+ renameData: PropTypes.func,
58
+ emptyStateTitle: PropTypes.string.isRequired,
59
+ };
60
+
61
+ Subcomponent.defaultProps = {
62
+ renameData: data => data,
63
+ };
64
+
65
+ return Subcomponent;
66
+ };
67
+
68
+ export default withLoading;
@@ -0,0 +1,5 @@
1
+ import { registerRoutes } from 'foremanReact/routes/RoutingService';
2
+
3
+ import routes from './routes/routes';
4
+
5
+ registerRoutes('foreman_openscap', routes);
@@ -0,0 +1,18 @@
1
+ query($search: String, $first: Int, $last: Int) {
2
+ cves(search: $search, first: $first, last: $last) {
3
+ totalCount
4
+ nodes {
5
+ id
6
+ refId
7
+ refUrl
8
+ hasErrata
9
+ definitionId
10
+ hosts {
11
+ nodes {
12
+ id
13
+ name
14
+ }
15
+ }
16
+ }
17
+ }
18
+ }
@@ -0,0 +1,11 @@
1
+ query($first: Int, $last: Int) {
2
+ ovalContents(first: $first, last: $last) {
3
+ totalCount
4
+ nodes {
5
+ id
6
+ name
7
+ url
8
+ originalFilename
9
+ }
10
+ }
11
+ }
@@ -0,0 +1,12 @@
1
+ query($first: Int, $last: Int) {
2
+ ovalPolicies(first: $first, last: $last) {
3
+ totalCount
4
+ nodes {
5
+ id
6
+ name
7
+ ovalContent {
8
+ name
9
+ }
10
+ }
11
+ }
12
+ }
@@ -0,0 +1,21 @@
1
+ query($id: String!) {
2
+ ovalPolicy(id: $id) {
3
+ id
4
+ name
5
+ period
6
+ cronLine
7
+ weekday
8
+ dayOfMonth
9
+ description
10
+ hostgroups {
11
+ nodes {
12
+ id
13
+ descendants {
14
+ nodes {
15
+ id
16
+ }
17
+ }
18
+ }
19
+ }
20
+ }
21
+ }
@@ -0,0 +1 @@
1
+ export const last = array => array[array.length - 1];
@@ -0,0 +1,13 @@
1
+ import { last } from './commonHelper';
2
+
3
+ const idSeparator = '-';
4
+ const versionSeparator = ':';
5
+ const defaultVersion = '01';
6
+
7
+ export const decodeId = model => {
8
+ const split = atob(model.id).split(idSeparator);
9
+ return parseInt(last(split), 10);
10
+ };
11
+
12
+ export const encodeId = (typename, id) =>
13
+ btoa([defaultVersion, versionSeparator, typename, idSeparator, id].join(''));
@@ -0,0 +1,31 @@
1
+ import URI from 'urijs';
2
+ import { useForemanSettings } from 'foremanReact/Root/Context/ForemanContext';
3
+
4
+ const parsePageParams = history => URI.parseQuery(history.location.search);
5
+
6
+ export const addSearch = (basePath, params) => {
7
+ let stringyfied = '';
8
+ if (Object.keys(params).length > 0) {
9
+ stringyfied = `?${URI.buildQuery(params)}`;
10
+ }
11
+
12
+ return `${basePath}${stringyfied}`;
13
+ };
14
+
15
+ export const useCurrentPagination = history => {
16
+ const pageParams = parsePageParams(history);
17
+ const uiSettings = useForemanSettings();
18
+
19
+ return {
20
+ page: parseInt(pageParams.page, 10) || 1,
21
+ perPage: parseInt(pageParams.perPage, 10) || uiSettings.perPage,
22
+ };
23
+ };
24
+
25
+ export const pageToVars = pagination => ({
26
+ first: pagination.page * pagination.perPage,
27
+ last: pagination.perPage,
28
+ });
29
+
30
+ export const useParamsToVars = history =>
31
+ pageToVars(useCurrentPagination(history));
@@ -0,0 +1,22 @@
1
+ import { decodeId } from './globalIdHelper';
2
+
3
+ const experimental = path => `/experimental${path}`;
4
+
5
+ const showPath = path => `${path}/:id`;
6
+
7
+ export const modelPath = (basePath, model) => `${basePath}/${decodeId(model)}`;
8
+
9
+ // react-router uses path-to-regexp, should we use it as well in a future?
10
+ // https://github.com/pillarjs/path-to-regexp/tree/v1.7.0#compile-reverse-path-to-regexp
11
+ export const resolvePath = (path, params) =>
12
+ Object.entries(params).reduce(
13
+ (memo, [key, value]) => memo.replace(key, value),
14
+ path
15
+ );
16
+
17
+ export const ovalContentsPath = experimental('/compliance/oval_contents');
18
+ export const ovalPoliciesPath = experimental('/compliance/oval_policies');
19
+ export const ovalPoliciesShowPath = `${showPath(ovalPoliciesPath)}/:tab?`;
20
+ export const hostsPath = '/hosts';
21
+ export const newJobPath = '/job_invocations/new';
22
+ export const hostsShowPath = showPath(hostsPath);
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ import { Link } from 'react-router-dom';
3
+ import { TableText } from '@patternfly/react-table';
4
+
5
+ export const linkCell = (path, text) => (
6
+ <TableText>
7
+ <Link to={path}>{text}</Link>
8
+ </TableText>
9
+ );
data/webpack/index.js ADDED
@@ -0,0 +1,8 @@
1
+ import componentRegistry from 'foremanReact/components/componentRegistry';
2
+
3
+ import RuleSeverity from './components/RuleSeverity';
4
+
5
+ componentRegistry.register({
6
+ name: 'RuleSeverity',
7
+ type: RuleSeverity,
8
+ });
@@ -0,0 +1,45 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { useQuery } from '@apollo/client';
4
+ import { translate as __ } from 'foremanReact/common/I18n';
5
+
6
+ import IndexLayout from '../../../components/IndexLayout';
7
+ import OvalContentsTable from './OvalContentsTable';
8
+ import {
9
+ useParamsToVars,
10
+ useCurrentPagination,
11
+ } from '../../../helpers/pageParamsHelper';
12
+ import ovalContentsQuery from '../../../graphql/queries/ovalContents.gql';
13
+
14
+ const OvalContentsIndex = props => {
15
+ const useFetchFn = componentProps =>
16
+ useQuery(ovalContentsQuery, {
17
+ variables: useParamsToVars(componentProps.history),
18
+ });
19
+
20
+ const renameData = data => ({
21
+ ovalContents: data.ovalContents.nodes,
22
+ totalCount: data.ovalContents.totalCount,
23
+ });
24
+
25
+ const pagination = useCurrentPagination(props.history);
26
+
27
+ return (
28
+ <IndexLayout pageTitle={__('OVAL Contents')}>
29
+ <OvalContentsTable
30
+ {...props}
31
+ fetchFn={useFetchFn}
32
+ renameData={renameData}
33
+ resultPath="ovalContents.nodes"
34
+ pagination={pagination}
35
+ emptyStateTitle={__('No OVAL Contents found.')}
36
+ />
37
+ </IndexLayout>
38
+ );
39
+ };
40
+
41
+ OvalContentsIndex.propTypes = {
42
+ history: PropTypes.object.isRequired,
43
+ };
44
+
45
+ export default OvalContentsIndex;
@@ -0,0 +1,38 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { translate as __ } from 'foremanReact/common/I18n';
4
+
5
+ import withLoading from '../../../components/withLoading';
6
+ import IndexTable from '../../../components/IndexTable';
7
+
8
+ const OvalContentsTable = props => {
9
+ const columns = [{ title: __('Name') }];
10
+
11
+ const rows = props.ovalContents.map(ovalContent => ({
12
+ cells: [{ title: ovalContent.name }],
13
+ ovalContent,
14
+ }));
15
+
16
+ const actions = [];
17
+
18
+ return (
19
+ <IndexTable
20
+ columns={columns}
21
+ rows={rows}
22
+ actions={actions}
23
+ pagination={props.pagination}
24
+ totalCount={props.totalCount}
25
+ history={props.history}
26
+ ariaTableLabel={__('OVAL Contents table')}
27
+ />
28
+ );
29
+ };
30
+
31
+ OvalContentsTable.propTypes = {
32
+ ovalContents: PropTypes.array.isRequired,
33
+ pagination: PropTypes.object.isRequired,
34
+ totalCount: PropTypes.number.isRequired,
35
+ history: PropTypes.object.isRequired,
36
+ };
37
+
38
+ export default withLoading(OvalContentsTable);