foreman_templates 7.0.1 → 7.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/.babelrc +16 -0
  3. data/lib/foreman_templates/version.rb +1 -1
  4. data/package.json +68 -0
  5. data/webpack/ForemanTemplates.js +29 -0
  6. data/webpack/Routes.js +33 -0
  7. data/webpack/__mocks__/foremanReact/common/helpers.js +27 -0
  8. data/webpack/__mocks__/foremanReact/components/Pagination/PaginationWrapper.js +2 -0
  9. data/webpack/__mocks__/foremanReact/components/common/forms/CommonForm.js +2 -0
  10. data/webpack/__mocks__/foremanReact/components/common/forms/Form.js +2 -0
  11. data/webpack/__mocks__/foremanReact/components/common/forms/TextField.js +2 -0
  12. data/webpack/__mocks__/foremanReact/redux/actions/common/forms.js +1 -0
  13. data/webpack/__mocks__/foremanReact/routes/common/PageLayout/PageLayout.js +2 -0
  14. data/webpack/__tests__/__snapshots__/helpers.test.js.snap +5 -0
  15. data/webpack/__tests__/helpers.test.js +17 -0
  16. data/webpack/components/NewTemplateSync/NewTemplateSync.js +60 -0
  17. data/webpack/components/NewTemplateSync/NewTemplateSync.scss +19 -0
  18. data/webpack/components/NewTemplateSync/NewTemplateSyncActions.js +39 -0
  19. data/webpack/components/NewTemplateSync/NewTemplateSyncReducer.js +34 -0
  20. data/webpack/components/NewTemplateSync/NewTemplateSyncSelectors.js +7 -0
  21. data/webpack/components/NewTemplateSync/__fixtures__/templateSyncSettings.fixtures.js +71 -0
  22. data/webpack/components/NewTemplateSync/__tests__/NewTemplateSync.test.js +31 -0
  23. data/webpack/components/NewTemplateSync/__tests__/NewTemplateSyncReducer.test.js +55 -0
  24. data/webpack/components/NewTemplateSync/__tests__/NewTemplateSyncSelectors.test.js +28 -0
  25. data/webpack/components/NewTemplateSync/__tests__/__snapshots__/NewTemplateSync.test.js.snap +53 -0
  26. data/webpack/components/NewTemplateSync/__tests__/__snapshots__/NewTemplateSyncReducer.test.js.snap +74 -0
  27. data/webpack/components/NewTemplateSync/__tests__/__snapshots__/NewTemplateSyncSelectors.test.js.snap +59 -0
  28. data/webpack/components/NewTemplateSync/components/ButtonTooltip.js +23 -0
  29. data/webpack/components/NewTemplateSync/components/NewTemplateSyncForm/NewTemplateSyncForm.js +145 -0
  30. data/webpack/components/NewTemplateSync/components/NewTemplateSyncForm/NewTemplateSyncFormConstants.js +1 -0
  31. data/webpack/components/NewTemplateSync/components/NewTemplateSyncForm/NewTemplateSyncFormSelectors.js +24 -0
  32. data/webpack/components/NewTemplateSync/components/NewTemplateSyncForm/__tests__/NewTemplateSyncForm.test.js +42 -0
  33. data/webpack/components/NewTemplateSync/components/NewTemplateSyncForm/__tests__/NewTemplateSyncFormSelectors.test.js +37 -0
  34. data/webpack/components/NewTemplateSync/components/NewTemplateSyncForm/__tests__/__snapshots__/NewTemplateSyncForm.test.js.snap +176 -0
  35. data/webpack/components/NewTemplateSync/components/NewTemplateSyncForm/__tests__/__snapshots__/NewTemplateSyncFormSelectors.test.js.snap +42 -0
  36. data/webpack/components/NewTemplateSync/components/NewTemplateSyncForm/index.js +44 -0
  37. data/webpack/components/NewTemplateSync/components/SyncSettingField.js +54 -0
  38. data/webpack/components/NewTemplateSync/components/SyncSettingFields.js +69 -0
  39. data/webpack/components/NewTemplateSync/components/SyncTypeRadios.js +52 -0
  40. data/webpack/components/NewTemplateSync/components/TextButtonField/BlankOption.js +19 -0
  41. data/webpack/components/NewTemplateSync/components/TextButtonField/CheckboxField.js +15 -0
  42. data/webpack/components/NewTemplateSync/components/TextButtonField/FieldType.js +46 -0
  43. data/webpack/components/NewTemplateSync/components/TextButtonField/InputField.js +14 -0
  44. data/webpack/components/NewTemplateSync/components/TextButtonField/RenderField.js +74 -0
  45. data/webpack/components/NewTemplateSync/components/TextButtonField/SelectField.js +24 -0
  46. data/webpack/components/NewTemplateSync/components/TextButtonField/index.js +69 -0
  47. data/webpack/components/NewTemplateSync/components/__tests__/SyncSettingField.test.js +34 -0
  48. data/webpack/components/NewTemplateSync/components/__tests__/SyncSettingFields.test.js +33 -0
  49. data/webpack/components/NewTemplateSync/components/__tests__/SyncTypeRadios.test.js +20 -0
  50. data/webpack/components/NewTemplateSync/components/__tests__/TextButtonField.test.js +65 -0
  51. data/webpack/components/NewTemplateSync/components/__tests__/__snapshots__/SyncSettingField.test.js.snap +131 -0
  52. data/webpack/components/NewTemplateSync/components/__tests__/__snapshots__/SyncSettingFields.test.js.snap +94 -0
  53. data/webpack/components/NewTemplateSync/components/__tests__/__snapshots__/SyncTypeRadios.test.js.snap +46 -0
  54. data/webpack/components/NewTemplateSync/components/__tests__/__snapshots__/TextButtonField.test.js.snap +112 -0
  55. data/webpack/components/NewTemplateSync/index.js +32 -0
  56. data/webpack/components/PageNotFound.js +13 -0
  57. data/webpack/components/PermissionDenied.js +33 -0
  58. data/webpack/components/TemplateSyncResult/TemplateSyncResult.js +61 -0
  59. data/webpack/components/TemplateSyncResult/TemplateSyncResult.scss +39 -0
  60. data/webpack/components/TemplateSyncResult/TemplateSyncResultActions.js +4 -0
  61. data/webpack/components/TemplateSyncResult/TemplateSyncResultHelpers.js +6 -0
  62. data/webpack/components/TemplateSyncResult/TemplateSyncResultReducer.js +33 -0
  63. data/webpack/components/TemplateSyncResult/TemplateSyncResultSelectors.js +1 -0
  64. data/webpack/components/TemplateSyncResult/__fixtures__/templateSyncResult.fixtures.js +86 -0
  65. data/webpack/components/TemplateSyncResult/__tests__/TemplateSyncResult.test.js +37 -0
  66. data/webpack/components/TemplateSyncResult/__tests__/TemplateSyncResultReducer.test.js +48 -0
  67. data/webpack/components/TemplateSyncResult/__tests__/__snapshots__/TemplateSyncResult.test.js.snap +112 -0
  68. data/webpack/components/TemplateSyncResult/__tests__/__snapshots__/TemplateSyncResultReducer.test.js.snap +88 -0
  69. data/webpack/components/TemplateSyncResult/components/EmptySyncResult.js +25 -0
  70. data/webpack/components/TemplateSyncResult/components/FinishedSyncResult.js +77 -0
  71. data/webpack/components/TemplateSyncResult/components/ListViewHeader.js +38 -0
  72. data/webpack/components/TemplateSyncResult/components/SyncResultList.js +41 -0
  73. data/webpack/components/TemplateSyncResult/components/SyncedTemplate/EmptyInfoItem.js +16 -0
  74. data/webpack/components/TemplateSyncResult/components/SyncedTemplate/IconInfoItem.js +21 -0
  75. data/webpack/components/TemplateSyncResult/components/SyncedTemplate/InfoItem.js +34 -0
  76. data/webpack/components/TemplateSyncResult/components/SyncedTemplate/LinkInfoItem.js +37 -0
  77. data/webpack/components/TemplateSyncResult/components/SyncedTemplate/StringInfoItem.js +50 -0
  78. data/webpack/components/TemplateSyncResult/components/SyncedTemplate/helpers.js +128 -0
  79. data/webpack/components/TemplateSyncResult/components/SyncedTemplate/index.js +33 -0
  80. data/webpack/components/TemplateSyncResult/components/__tests__/SyncResultList.test.js +27 -0
  81. data/webpack/components/TemplateSyncResult/components/__tests__/SyncedTemplate.test.js +30 -0
  82. data/webpack/components/TemplateSyncResult/components/__tests__/__snapshots__/SyncResultList.test.js.snap +102 -0
  83. data/webpack/components/TemplateSyncResult/components/__tests__/__snapshots__/SyncedTemplate.test.js.snap +548 -0
  84. data/webpack/components/TemplateSyncResult/index.js +13 -0
  85. data/webpack/consts.js +6 -0
  86. data/webpack/index.js +11 -0
  87. data/webpack/reducer.js +6 -0
  88. data/webpack/testSetup.js +11 -0
  89. data/webpack/withProtectedView.js +16 -0
  90. metadata +89 -2
@@ -0,0 +1,128 @@
1
+ import React from 'react';
2
+ import { isEmpty } from 'lodash';
3
+ import { Icon } from 'patternfly-react';
4
+
5
+ import IconInfoItem from './IconInfoItem';
6
+ import EmptyInfoItem from './EmptyInfoItem';
7
+ import StringInfoItem from './StringInfoItem';
8
+ import LinkInfoItem from './LinkInfoItem';
9
+
10
+ export const itemIteratorId = (template, attr) =>
11
+ `${template.templateFile}-${attr}`;
12
+
13
+ export const additionalInfo = (template, editPath) => {
14
+ const infoAttrs = [
15
+ 'name',
16
+ 'locked',
17
+ 'snippet',
18
+ 'humanizedClassName',
19
+ 'kind',
20
+ 'templateFile',
21
+ ];
22
+
23
+ return infoAttrs.map(attr => {
24
+ const key = itemIteratorId(template, attr);
25
+
26
+ const classNameMap = { Ptable: 'Partition Table' };
27
+
28
+ if (!template[attr]) {
29
+ return <EmptyInfoItem template={template} attr={attr} key={key} />;
30
+ }
31
+
32
+ switch (attr) {
33
+ case 'locked':
34
+ return (
35
+ <IconInfoItem
36
+ template={template}
37
+ attr={attr}
38
+ iconName="lock"
39
+ tooltipText="Locked"
40
+ key={key}
41
+ />
42
+ );
43
+ case 'snippet':
44
+ return (
45
+ <IconInfoItem
46
+ template={template}
47
+ attr={attr}
48
+ iconName="check"
49
+ tooltipText="Snippet"
50
+ key={key}
51
+ />
52
+ );
53
+ case 'humanizedClassName':
54
+ return (
55
+ <StringInfoItem
56
+ template={template}
57
+ attr={attr}
58
+ translate
59
+ mapAttr={(templateObj, attribute) =>
60
+ classNameMap[templateObj[attribute]]
61
+ ? classNameMap[templateObj[attribute]]
62
+ : templateObj[attribute]
63
+ }
64
+ key={key}
65
+ />
66
+ );
67
+ case 'kind':
68
+ return <StringInfoItem template={template} attr={attr} key={key} />;
69
+ case 'templateFile':
70
+ return (
71
+ <StringInfoItem template={template} attr={attr} key={key} elipsed />
72
+ );
73
+ case 'name':
74
+ return (
75
+ <LinkInfoItem template={template} editPath={editPath} attr={attr} />
76
+ );
77
+ default:
78
+ return '';
79
+ }
80
+ });
81
+ };
82
+
83
+ export const itemLeftContentIcon = template => {
84
+ let iconName = template.additionalInfo ? 'warning-triangle-o' : undefined;
85
+
86
+ if (!iconName) {
87
+ iconName = isEmpty(aggregatedErrors(template)) ? 'ok' : 'error-circle-o';
88
+ }
89
+ return <Icon name={iconName} size="sm" type="pf" />;
90
+ };
91
+
92
+ export const expandableContent = template => {
93
+ if (Object.keys(aggregatedMessages(template)).length !== 0) {
94
+ const res = Object.keys(aggregatedMessages(template)).map(key => (
95
+ <li key={itemIteratorId(template, key)}>
96
+ {formatError(key, aggregatedMessages(template)[key])}
97
+ </li>
98
+ ));
99
+ return <ul>{res}</ul>;
100
+ }
101
+ return <span>There were no errors.</span>;
102
+ };
103
+
104
+ const aggregatedErrors = template => {
105
+ const err = { ...template.errors } || {};
106
+ if (template.additionalErrors) {
107
+ err.additional = template.additionalErrors;
108
+ }
109
+
110
+ return err;
111
+ };
112
+
113
+ const aggregatedMessages = template => {
114
+ const errors = aggregatedErrors(template);
115
+ if (template.additionalInfo) {
116
+ errors.info = template.additionalInfo;
117
+ }
118
+ return errors;
119
+ };
120
+
121
+ const formatError = (key, value) => {
122
+ const omitKeys = ['base', 'additional', 'info'];
123
+ if (omitKeys.reduce((memo, item) => memo || key === item, false)) {
124
+ return value;
125
+ }
126
+
127
+ return `${key}: ${value}`;
128
+ };
@@ -0,0 +1,33 @@
1
+ import React from 'react';
2
+ import { ListView } from 'patternfly-react';
3
+ import PropTypes from 'prop-types';
4
+
5
+ import {
6
+ expandableContent,
7
+ itemLeftContentIcon,
8
+ additionalInfo,
9
+ } from './helpers';
10
+
11
+ const SyncedTemplate = ({ template, editPath }) => (
12
+ <ListView.Item
13
+ key={template.id}
14
+ additionalInfo={additionalInfo(template, editPath)}
15
+ className="listViewItem--listItemVariants"
16
+ leftContent={itemLeftContentIcon(template)}
17
+ hideCloseIcon
18
+ stacked
19
+ >
20
+ {expandableContent(template)}
21
+ </ListView.Item>
22
+ );
23
+
24
+ SyncedTemplate.propTypes = {
25
+ template: PropTypes.object.isRequired,
26
+ editPath: PropTypes.string,
27
+ };
28
+
29
+ SyncedTemplate.defaultProps = {
30
+ editPath: '',
31
+ };
32
+
33
+ export default SyncedTemplate;
@@ -0,0 +1,27 @@
1
+ import { testComponentSnapshotsWithFixtures } from 'react-redux-test-utils';
2
+
3
+ import SyncResultList from '../SyncResultList';
4
+ import { importTemplates } from '../../__fixtures__/templateSyncResult.fixtures';
5
+
6
+ const noop = () => {};
7
+
8
+ const editPaths = {
9
+ JobTemplate: '',
10
+ Ptable: '',
11
+ ProvisioningTemplate: '',
12
+ };
13
+
14
+ const fixtures = {
15
+ 'should render': {
16
+ pageChange: noop,
17
+ templates: importTemplates,
18
+ editPaths,
19
+ pagination: {
20
+ page: 1,
21
+ perPage: 20,
22
+ },
23
+ },
24
+ };
25
+
26
+ describe('SyncResultList', () =>
27
+ testComponentSnapshotsWithFixtures(SyncResultList, fixtures));
@@ -0,0 +1,30 @@
1
+ import { testComponentSnapshotsWithFixtures } from 'react-redux-test-utils';
2
+ import SyncedTemplate from '../SyncedTemplate';
3
+ import {
4
+ noName,
5
+ epel,
6
+ coreos,
7
+ filteredOut,
8
+ } from '../../__fixtures__/templateSyncResult.fixtures';
9
+
10
+ const fixtures = {
11
+ 'should render template with invalid metadata': {
12
+ template: noName,
13
+ editPath: '',
14
+ },
15
+ 'should render template with validation errors': {
16
+ template: epel,
17
+ editPath: '/templates/:id/edit',
18
+ },
19
+ 'should render template without errros': {
20
+ template: coreos,
21
+ editPath: '/ptables/:id/edit',
22
+ },
23
+ 'should render skipped template': {
24
+ template: filteredOut,
25
+ editPath: '/ptables/:id/edit',
26
+ },
27
+ };
28
+
29
+ describe('SyncedTemplate', () =>
30
+ testComponentSnapshotsWithFixtures(SyncedTemplate, fixtures));
@@ -0,0 +1,102 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`SyncResultList should render 1`] = `
4
+ <ListView
5
+ className=""
6
+ >
7
+ <ListViewHeader />
8
+ <SyncedTemplate
9
+ editPath=""
10
+ key="null"
11
+ template={
12
+ Object {
13
+ "additionalErrors": "No \\"name\\" found in metadata",
14
+ "errors": null,
15
+ "name": null,
16
+ "templateFile": "random_template.erb",
17
+ }
18
+ }
19
+ />
20
+ <SyncedTemplate
21
+ editPath=""
22
+ key="EPEL"
23
+ template={
24
+ Object {
25
+ "additionalErrors": null,
26
+ "className": "ProvisioningTemplate",
27
+ "errors": Object {
28
+ "base": Array [
29
+ "This template is locked",
30
+ ],
31
+ },
32
+ "humanizedClassName": "Provisioning Template",
33
+ "kind": "Provision",
34
+ "locked": true,
35
+ "name": "EPEL",
36
+ "snippet": true,
37
+ "templateFile": "epel.erb",
38
+ }
39
+ }
40
+ />
41
+ <SyncedTemplate
42
+ editPath=""
43
+ key="CoreOS default"
44
+ template={
45
+ Object {
46
+ "additionalErrors": null,
47
+ "className": "Ptable",
48
+ "errors": Object {},
49
+ "humanizedClassName": "Ptable",
50
+ "locked": false,
51
+ "name": "CoreOS default",
52
+ "snippet": false,
53
+ "templateFile": "coreos_default.erb",
54
+ }
55
+ }
56
+ />
57
+ <SyncedTemplate
58
+ editPath=""
59
+ key="null"
60
+ template={
61
+ Object {
62
+ "additionalErrors": "No \\"model\\" found in metadata",
63
+ "errors": null,
64
+ "name": null,
65
+ "templateFile": "no_model.erb",
66
+ }
67
+ }
68
+ />
69
+ <SyncedTemplate
70
+ editPath=""
71
+ key="Kickstart fake"
72
+ template={
73
+ Object {
74
+ "additionalErrors": null,
75
+ "className": "ProvisioningTemplate",
76
+ "errors": Object {
77
+ "name": Array [
78
+ "has already been taken",
79
+ ],
80
+ },
81
+ "humanizedClassName": "Provisioning Template",
82
+ "locked": true,
83
+ "name": "Kickstart fake",
84
+ "snippet": true,
85
+ "templateFile": "kickstart_fake.erb",
86
+ }
87
+ }
88
+ />
89
+ <PaginationWrapper
90
+ dropdownButtonId="template-sync-result-dropdown"
91
+ itemCount={5}
92
+ onChange={[Function]}
93
+ pagination={
94
+ Object {
95
+ "page": 1,
96
+ "perPage": 20,
97
+ }
98
+ }
99
+ viewType="list"
100
+ />
101
+ </ListView>
102
+ `;