foreman_openscap 4.3.0 → 4.3.1

Sign up to get free protection for your applications and to get access to all the features.
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);