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.
- checksums.yaml +4 -4
- data/.babelrc +16 -0
- data/lib/foreman_templates/version.rb +1 -1
- data/package.json +68 -0
- data/webpack/ForemanTemplates.js +29 -0
- data/webpack/Routes.js +33 -0
- data/webpack/__mocks__/foremanReact/common/helpers.js +27 -0
- data/webpack/__mocks__/foremanReact/components/Pagination/PaginationWrapper.js +2 -0
- data/webpack/__mocks__/foremanReact/components/common/forms/CommonForm.js +2 -0
- data/webpack/__mocks__/foremanReact/components/common/forms/Form.js +2 -0
- data/webpack/__mocks__/foremanReact/components/common/forms/TextField.js +2 -0
- data/webpack/__mocks__/foremanReact/redux/actions/common/forms.js +1 -0
- data/webpack/__mocks__/foremanReact/routes/common/PageLayout/PageLayout.js +2 -0
- data/webpack/__tests__/__snapshots__/helpers.test.js.snap +5 -0
- data/webpack/__tests__/helpers.test.js +17 -0
- data/webpack/components/NewTemplateSync/NewTemplateSync.js +60 -0
- data/webpack/components/NewTemplateSync/NewTemplateSync.scss +19 -0
- data/webpack/components/NewTemplateSync/NewTemplateSyncActions.js +39 -0
- data/webpack/components/NewTemplateSync/NewTemplateSyncReducer.js +34 -0
- data/webpack/components/NewTemplateSync/NewTemplateSyncSelectors.js +7 -0
- data/webpack/components/NewTemplateSync/__fixtures__/templateSyncSettings.fixtures.js +71 -0
- data/webpack/components/NewTemplateSync/__tests__/NewTemplateSync.test.js +31 -0
- data/webpack/components/NewTemplateSync/__tests__/NewTemplateSyncReducer.test.js +55 -0
- data/webpack/components/NewTemplateSync/__tests__/NewTemplateSyncSelectors.test.js +28 -0
- data/webpack/components/NewTemplateSync/__tests__/__snapshots__/NewTemplateSync.test.js.snap +53 -0
- data/webpack/components/NewTemplateSync/__tests__/__snapshots__/NewTemplateSyncReducer.test.js.snap +74 -0
- data/webpack/components/NewTemplateSync/__tests__/__snapshots__/NewTemplateSyncSelectors.test.js.snap +59 -0
- data/webpack/components/NewTemplateSync/components/ButtonTooltip.js +23 -0
- data/webpack/components/NewTemplateSync/components/NewTemplateSyncForm/NewTemplateSyncForm.js +145 -0
- data/webpack/components/NewTemplateSync/components/NewTemplateSyncForm/NewTemplateSyncFormConstants.js +1 -0
- data/webpack/components/NewTemplateSync/components/NewTemplateSyncForm/NewTemplateSyncFormSelectors.js +24 -0
- data/webpack/components/NewTemplateSync/components/NewTemplateSyncForm/__tests__/NewTemplateSyncForm.test.js +42 -0
- data/webpack/components/NewTemplateSync/components/NewTemplateSyncForm/__tests__/NewTemplateSyncFormSelectors.test.js +37 -0
- data/webpack/components/NewTemplateSync/components/NewTemplateSyncForm/__tests__/__snapshots__/NewTemplateSyncForm.test.js.snap +176 -0
- data/webpack/components/NewTemplateSync/components/NewTemplateSyncForm/__tests__/__snapshots__/NewTemplateSyncFormSelectors.test.js.snap +42 -0
- data/webpack/components/NewTemplateSync/components/NewTemplateSyncForm/index.js +44 -0
- data/webpack/components/NewTemplateSync/components/SyncSettingField.js +54 -0
- data/webpack/components/NewTemplateSync/components/SyncSettingFields.js +69 -0
- data/webpack/components/NewTemplateSync/components/SyncTypeRadios.js +52 -0
- data/webpack/components/NewTemplateSync/components/TextButtonField/BlankOption.js +19 -0
- data/webpack/components/NewTemplateSync/components/TextButtonField/CheckboxField.js +15 -0
- data/webpack/components/NewTemplateSync/components/TextButtonField/FieldType.js +46 -0
- data/webpack/components/NewTemplateSync/components/TextButtonField/InputField.js +14 -0
- data/webpack/components/NewTemplateSync/components/TextButtonField/RenderField.js +74 -0
- data/webpack/components/NewTemplateSync/components/TextButtonField/SelectField.js +24 -0
- data/webpack/components/NewTemplateSync/components/TextButtonField/index.js +69 -0
- data/webpack/components/NewTemplateSync/components/__tests__/SyncSettingField.test.js +34 -0
- data/webpack/components/NewTemplateSync/components/__tests__/SyncSettingFields.test.js +33 -0
- data/webpack/components/NewTemplateSync/components/__tests__/SyncTypeRadios.test.js +20 -0
- data/webpack/components/NewTemplateSync/components/__tests__/TextButtonField.test.js +65 -0
- data/webpack/components/NewTemplateSync/components/__tests__/__snapshots__/SyncSettingField.test.js.snap +131 -0
- data/webpack/components/NewTemplateSync/components/__tests__/__snapshots__/SyncSettingFields.test.js.snap +94 -0
- data/webpack/components/NewTemplateSync/components/__tests__/__snapshots__/SyncTypeRadios.test.js.snap +46 -0
- data/webpack/components/NewTemplateSync/components/__tests__/__snapshots__/TextButtonField.test.js.snap +112 -0
- data/webpack/components/NewTemplateSync/index.js +32 -0
- data/webpack/components/PageNotFound.js +13 -0
- data/webpack/components/PermissionDenied.js +33 -0
- data/webpack/components/TemplateSyncResult/TemplateSyncResult.js +61 -0
- data/webpack/components/TemplateSyncResult/TemplateSyncResult.scss +39 -0
- data/webpack/components/TemplateSyncResult/TemplateSyncResultActions.js +4 -0
- data/webpack/components/TemplateSyncResult/TemplateSyncResultHelpers.js +6 -0
- data/webpack/components/TemplateSyncResult/TemplateSyncResultReducer.js +33 -0
- data/webpack/components/TemplateSyncResult/TemplateSyncResultSelectors.js +1 -0
- data/webpack/components/TemplateSyncResult/__fixtures__/templateSyncResult.fixtures.js +86 -0
- data/webpack/components/TemplateSyncResult/__tests__/TemplateSyncResult.test.js +37 -0
- data/webpack/components/TemplateSyncResult/__tests__/TemplateSyncResultReducer.test.js +48 -0
- data/webpack/components/TemplateSyncResult/__tests__/__snapshots__/TemplateSyncResult.test.js.snap +112 -0
- data/webpack/components/TemplateSyncResult/__tests__/__snapshots__/TemplateSyncResultReducer.test.js.snap +88 -0
- data/webpack/components/TemplateSyncResult/components/EmptySyncResult.js +25 -0
- data/webpack/components/TemplateSyncResult/components/FinishedSyncResult.js +77 -0
- data/webpack/components/TemplateSyncResult/components/ListViewHeader.js +38 -0
- data/webpack/components/TemplateSyncResult/components/SyncResultList.js +41 -0
- data/webpack/components/TemplateSyncResult/components/SyncedTemplate/EmptyInfoItem.js +16 -0
- data/webpack/components/TemplateSyncResult/components/SyncedTemplate/IconInfoItem.js +21 -0
- data/webpack/components/TemplateSyncResult/components/SyncedTemplate/InfoItem.js +34 -0
- data/webpack/components/TemplateSyncResult/components/SyncedTemplate/LinkInfoItem.js +37 -0
- data/webpack/components/TemplateSyncResult/components/SyncedTemplate/StringInfoItem.js +50 -0
- data/webpack/components/TemplateSyncResult/components/SyncedTemplate/helpers.js +128 -0
- data/webpack/components/TemplateSyncResult/components/SyncedTemplate/index.js +33 -0
- data/webpack/components/TemplateSyncResult/components/__tests__/SyncResultList.test.js +27 -0
- data/webpack/components/TemplateSyncResult/components/__tests__/SyncedTemplate.test.js +30 -0
- data/webpack/components/TemplateSyncResult/components/__tests__/__snapshots__/SyncResultList.test.js.snap +102 -0
- data/webpack/components/TemplateSyncResult/components/__tests__/__snapshots__/SyncedTemplate.test.js.snap +548 -0
- data/webpack/components/TemplateSyncResult/index.js +13 -0
- data/webpack/consts.js +6 -0
- data/webpack/index.js +11 -0
- data/webpack/reducer.js +6 -0
- data/webpack/testSetup.js +11 -0
- data/webpack/withProtectedView.js +16 -0
- metadata +89 -2
@@ -0,0 +1,131 @@
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
2
|
+
|
3
|
+
exports[`SyncSettingField should render boolean setting as checkbox 1`] = `
|
4
|
+
<TextButtonField
|
5
|
+
blank={Object {}}
|
6
|
+
buttonAttrs={
|
7
|
+
Object {
|
8
|
+
"buttonAction": [Function],
|
9
|
+
"buttonText": <ButtonTooltip
|
10
|
+
tooltipId="force"
|
11
|
+
/>,
|
12
|
+
}
|
13
|
+
}
|
14
|
+
className=""
|
15
|
+
disabled={false}
|
16
|
+
fieldRequired={false}
|
17
|
+
fieldSelector={[Function]}
|
18
|
+
inputClassName="col-md-6"
|
19
|
+
item={
|
20
|
+
Object {
|
21
|
+
"id": 46,
|
22
|
+
"name": "force",
|
23
|
+
"settingsType": "bool",
|
24
|
+
"value": false,
|
25
|
+
}
|
26
|
+
}
|
27
|
+
label="undefined "
|
28
|
+
name="force"
|
29
|
+
tooltipHelp={
|
30
|
+
<FieldLevelHelp
|
31
|
+
buttonClass=""
|
32
|
+
content={null}
|
33
|
+
placement="top"
|
34
|
+
rootClose={true}
|
35
|
+
/>
|
36
|
+
}
|
37
|
+
validate={Array []}
|
38
|
+
/>
|
39
|
+
`;
|
40
|
+
|
41
|
+
exports[`SyncSettingField should render setting with input field 1`] = `
|
42
|
+
<TextButtonField
|
43
|
+
blank={Object {}}
|
44
|
+
buttonAttrs={
|
45
|
+
Object {
|
46
|
+
"buttonAction": [Function],
|
47
|
+
"buttonText": <ButtonTooltip
|
48
|
+
tooltipId="filter"
|
49
|
+
/>,
|
50
|
+
}
|
51
|
+
}
|
52
|
+
className=""
|
53
|
+
disabled={false}
|
54
|
+
fieldRequired={false}
|
55
|
+
fieldSelector={[Function]}
|
56
|
+
inputClassName="col-md-6"
|
57
|
+
item={
|
58
|
+
Object {
|
59
|
+
"id": 47,
|
60
|
+
"name": "filter",
|
61
|
+
"settingsType": "string",
|
62
|
+
"value": "",
|
63
|
+
}
|
64
|
+
}
|
65
|
+
label="undefined "
|
66
|
+
name="filter"
|
67
|
+
tooltipHelp={
|
68
|
+
<FieldLevelHelp
|
69
|
+
buttonClass=""
|
70
|
+
content={null}
|
71
|
+
placement="top"
|
72
|
+
rootClose={true}
|
73
|
+
/>
|
74
|
+
}
|
75
|
+
validate={Array []}
|
76
|
+
/>
|
77
|
+
`;
|
78
|
+
|
79
|
+
exports[`SyncSettingField should render setting with select choices 1`] = `
|
80
|
+
<TextButtonField
|
81
|
+
blank={Object {}}
|
82
|
+
buttonAttrs={
|
83
|
+
Object {
|
84
|
+
"buttonAction": [Function],
|
85
|
+
"buttonText": <ButtonTooltip
|
86
|
+
tooltipId="associate"
|
87
|
+
/>,
|
88
|
+
}
|
89
|
+
}
|
90
|
+
className=""
|
91
|
+
disabled={false}
|
92
|
+
fieldRequired={false}
|
93
|
+
fieldSelector={[Function]}
|
94
|
+
inputClassName="col-md-6"
|
95
|
+
item={
|
96
|
+
Object {
|
97
|
+
"id": 45,
|
98
|
+
"name": "associate",
|
99
|
+
"selection": Array [
|
100
|
+
Object {
|
101
|
+
"label": "New",
|
102
|
+
"value": "new",
|
103
|
+
},
|
104
|
+
Object {
|
105
|
+
"label": "Never",
|
106
|
+
"value": "never",
|
107
|
+
},
|
108
|
+
Object {
|
109
|
+
"label": "Always",
|
110
|
+
"value": "always",
|
111
|
+
},
|
112
|
+
],
|
113
|
+
"settingsType": "string",
|
114
|
+
"value": "new",
|
115
|
+
}
|
116
|
+
}
|
117
|
+
label="undefined "
|
118
|
+
name="associate"
|
119
|
+
tooltipHelp={
|
120
|
+
<FieldLevelHelp
|
121
|
+
buttonClass=""
|
122
|
+
content={null}
|
123
|
+
placement="top"
|
124
|
+
rootClose={true}
|
125
|
+
/>
|
126
|
+
}
|
127
|
+
validate={Array []}
|
128
|
+
>
|
129
|
+
new
|
130
|
+
</TextButtonField>
|
131
|
+
`;
|
@@ -0,0 +1,94 @@
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
2
|
+
|
3
|
+
exports[`SyncSettingFields should show export settings 1`] = `
|
4
|
+
<Fragment>
|
5
|
+
<SyncSettingField
|
6
|
+
disabled={false}
|
7
|
+
key="filter"
|
8
|
+
resetField={[Function]}
|
9
|
+
setting={
|
10
|
+
Object {
|
11
|
+
"id": 47,
|
12
|
+
"name": "filter",
|
13
|
+
"settingsType": "string",
|
14
|
+
"value": "",
|
15
|
+
}
|
16
|
+
}
|
17
|
+
/>
|
18
|
+
<SyncSettingField
|
19
|
+
disabled={false}
|
20
|
+
key="negate"
|
21
|
+
resetField={[Function]}
|
22
|
+
setting={
|
23
|
+
Object {
|
24
|
+
"id": 48,
|
25
|
+
"name": "negate",
|
26
|
+
"settingsType": "bool",
|
27
|
+
"value": false,
|
28
|
+
}
|
29
|
+
}
|
30
|
+
/>
|
31
|
+
<SyncSettingField
|
32
|
+
disabled={false}
|
33
|
+
key="repo"
|
34
|
+
resetField={[Function]}
|
35
|
+
setting={
|
36
|
+
Object {
|
37
|
+
"id": 49,
|
38
|
+
"name": "repo",
|
39
|
+
"required": true,
|
40
|
+
"settingsType": "string",
|
41
|
+
"validate": Array [
|
42
|
+
[Function],
|
43
|
+
],
|
44
|
+
"value": "https://github.com/theforeman/community-templates.git",
|
45
|
+
}
|
46
|
+
}
|
47
|
+
/>
|
48
|
+
</Fragment>
|
49
|
+
`;
|
50
|
+
|
51
|
+
exports[`SyncSettingFields should show import settings 1`] = `
|
52
|
+
<Fragment>
|
53
|
+
<SyncSettingField
|
54
|
+
disabled={false}
|
55
|
+
key="associate"
|
56
|
+
resetField={[Function]}
|
57
|
+
setting={
|
58
|
+
Object {
|
59
|
+
"id": 45,
|
60
|
+
"name": "associate",
|
61
|
+
"selection": Array [
|
62
|
+
Object {
|
63
|
+
"label": "New",
|
64
|
+
"value": "new",
|
65
|
+
},
|
66
|
+
Object {
|
67
|
+
"label": "Never",
|
68
|
+
"value": "never",
|
69
|
+
},
|
70
|
+
Object {
|
71
|
+
"label": "Always",
|
72
|
+
"value": "always",
|
73
|
+
},
|
74
|
+
],
|
75
|
+
"settingsType": "string",
|
76
|
+
"value": "new",
|
77
|
+
}
|
78
|
+
}
|
79
|
+
/>
|
80
|
+
<SyncSettingField
|
81
|
+
disabled={false}
|
82
|
+
key="force"
|
83
|
+
resetField={[Function]}
|
84
|
+
setting={
|
85
|
+
Object {
|
86
|
+
"id": 46,
|
87
|
+
"name": "force",
|
88
|
+
"settingsType": "bool",
|
89
|
+
"value": false,
|
90
|
+
}
|
91
|
+
}
|
92
|
+
/>
|
93
|
+
</Fragment>
|
94
|
+
`;
|
@@ -0,0 +1,46 @@
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
2
|
+
|
3
|
+
exports[`SyncTypeRadios should render 1`] = `
|
4
|
+
<CommonForm
|
5
|
+
className=""
|
6
|
+
inputClassName="col-md-6"
|
7
|
+
label="Test radios"
|
8
|
+
>
|
9
|
+
<Radio
|
10
|
+
bsClass="radio"
|
11
|
+
checked={false}
|
12
|
+
disabled={false}
|
13
|
+
inline={true}
|
14
|
+
key="0"
|
15
|
+
onChange={[Function]}
|
16
|
+
title="A"
|
17
|
+
value="a"
|
18
|
+
>
|
19
|
+
A
|
20
|
+
</Radio>
|
21
|
+
<Radio
|
22
|
+
bsClass="radio"
|
23
|
+
checked={true}
|
24
|
+
disabled={false}
|
25
|
+
inline={true}
|
26
|
+
key="1"
|
27
|
+
onChange={[Function]}
|
28
|
+
title="B"
|
29
|
+
value="b"
|
30
|
+
>
|
31
|
+
B
|
32
|
+
</Radio>
|
33
|
+
<Radio
|
34
|
+
bsClass="radio"
|
35
|
+
checked={false}
|
36
|
+
disabled={false}
|
37
|
+
inline={true}
|
38
|
+
key="2"
|
39
|
+
onChange={[Function]}
|
40
|
+
title="C"
|
41
|
+
value="c"
|
42
|
+
>
|
43
|
+
C
|
44
|
+
</Radio>
|
45
|
+
</CommonForm>
|
46
|
+
`;
|
@@ -0,0 +1,112 @@
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
2
|
+
|
3
|
+
exports[`TextButtonField should render checkbox item 1`] = `
|
4
|
+
<Field
|
5
|
+
blank={Object {}}
|
6
|
+
buttonAttrs={
|
7
|
+
Object {
|
8
|
+
"buttonAction": [Function],
|
9
|
+
"buttonText": "Button",
|
10
|
+
}
|
11
|
+
}
|
12
|
+
component={[Function]}
|
13
|
+
disabled={false}
|
14
|
+
fieldRequired={false}
|
15
|
+
fieldSelector={[Function]}
|
16
|
+
item={
|
17
|
+
Object {
|
18
|
+
"type": "checkbox",
|
19
|
+
}
|
20
|
+
}
|
21
|
+
label="Checkbox"
|
22
|
+
name="Checkbox field"
|
23
|
+
tooltipHelp={null}
|
24
|
+
/>
|
25
|
+
`;
|
26
|
+
|
27
|
+
exports[`TextButtonField should render select item with custom blank opt 1`] = `
|
28
|
+
<Field
|
29
|
+
blank={
|
30
|
+
Object {
|
31
|
+
"label": "Bare Metal",
|
32
|
+
"value": "bareMetal",
|
33
|
+
}
|
34
|
+
}
|
35
|
+
buttonAttrs={
|
36
|
+
Object {
|
37
|
+
"buttonAction": [Function],
|
38
|
+
"buttonText": "Button",
|
39
|
+
}
|
40
|
+
}
|
41
|
+
component={[Function]}
|
42
|
+
disabled={false}
|
43
|
+
fieldRequired={false}
|
44
|
+
fieldSelector={[Function]}
|
45
|
+
item={
|
46
|
+
Object {
|
47
|
+
"selection": Array [
|
48
|
+
Object {
|
49
|
+
"label": "A",
|
50
|
+
"value": "a",
|
51
|
+
},
|
52
|
+
Object {
|
53
|
+
"label": "B",
|
54
|
+
"value": "b",
|
55
|
+
},
|
56
|
+
Object {
|
57
|
+
"label": "C",
|
58
|
+
"value": "c",
|
59
|
+
},
|
60
|
+
],
|
61
|
+
"type": "select",
|
62
|
+
}
|
63
|
+
}
|
64
|
+
label="Select"
|
65
|
+
name="select field"
|
66
|
+
tooltipHelp={null}
|
67
|
+
/>
|
68
|
+
`;
|
69
|
+
|
70
|
+
exports[`TextButtonField should render text field without field selector 1`] = `
|
71
|
+
<Field
|
72
|
+
blank={Object {}}
|
73
|
+
buttonAttrs={
|
74
|
+
Object {
|
75
|
+
"buttonAction": [Function],
|
76
|
+
"buttonText": "Button",
|
77
|
+
}
|
78
|
+
}
|
79
|
+
component={[Function]}
|
80
|
+
disabled={false}
|
81
|
+
fieldRequired={false}
|
82
|
+
fieldSelector={[Function]}
|
83
|
+
item={Object {}}
|
84
|
+
label="Text field"
|
85
|
+
name="no selector"
|
86
|
+
tooltipHelp={null}
|
87
|
+
/>
|
88
|
+
`;
|
89
|
+
|
90
|
+
exports[`TextButtonField should render text item 1`] = `
|
91
|
+
<Field
|
92
|
+
blank={Object {}}
|
93
|
+
buttonAttrs={
|
94
|
+
Object {
|
95
|
+
"buttonAction": [Function],
|
96
|
+
"buttonText": "Button",
|
97
|
+
}
|
98
|
+
}
|
99
|
+
component={[Function]}
|
100
|
+
disabled={false}
|
101
|
+
fieldRequired={false}
|
102
|
+
fieldSelector={[Function]}
|
103
|
+
item={
|
104
|
+
Object {
|
105
|
+
"type": "text",
|
106
|
+
}
|
107
|
+
}
|
108
|
+
label="Text"
|
109
|
+
name="Text field"
|
110
|
+
tooltipHelp={null}
|
111
|
+
/>
|
112
|
+
`;
|
@@ -0,0 +1,32 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { connect } from 'react-redux';
|
3
|
+
|
4
|
+
import * as TemplateSyncActions from './NewTemplateSyncActions';
|
5
|
+
import NewTemplateSync from './NewTemplateSync';
|
6
|
+
import { selectLoadingSettings, selectError } from './NewTemplateSyncSelectors';
|
7
|
+
import withProtectedView from '../../withProtectedView';
|
8
|
+
import PermissionDenied from '../PermissionDenied';
|
9
|
+
|
10
|
+
const mapStateToProps = state => ({
|
11
|
+
loadingSettings: selectLoadingSettings(state),
|
12
|
+
error: selectError(state),
|
13
|
+
});
|
14
|
+
|
15
|
+
const permissionList = (
|
16
|
+
<ul className="list-unstyled">
|
17
|
+
<li>import_templates</li>
|
18
|
+
<li>export_templates</li>
|
19
|
+
</ul>
|
20
|
+
);
|
21
|
+
|
22
|
+
export default withProtectedView(
|
23
|
+
connect(
|
24
|
+
mapStateToProps,
|
25
|
+
TemplateSyncActions
|
26
|
+
)(NewTemplateSync),
|
27
|
+
PermissionDenied,
|
28
|
+
props =>
|
29
|
+
props.userPermissions &&
|
30
|
+
(props.userPermissions.import || props.userPermissions.export),
|
31
|
+
{ doc: permissionList }
|
32
|
+
);
|
@@ -0,0 +1,13 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { EmptyStatePattern as EmptyState } from 'foremanReact/components/common/EmptyState';
|
3
|
+
|
4
|
+
const PageNotFound = props => (
|
5
|
+
<EmptyState
|
6
|
+
iconType="fa"
|
7
|
+
icon="exclamation-triangle"
|
8
|
+
header={__('Page Not Found')}
|
9
|
+
description={__('The page you are looking for does not exist')}
|
10
|
+
/>
|
11
|
+
);
|
12
|
+
|
13
|
+
export default PageNotFound;
|
@@ -0,0 +1,33 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import PropTypes from 'prop-types';
|
3
|
+
|
4
|
+
import { EmptyStatePattern as EmptyState } from 'foremanReact/components/common/EmptyState';
|
5
|
+
|
6
|
+
const PermissionDenied = props => {
|
7
|
+
const description = (
|
8
|
+
<span>
|
9
|
+
{__('You are not authorized to perform this action.')}
|
10
|
+
<br />
|
11
|
+
{__(
|
12
|
+
'Please request one of the required permissions listed below from a Foreman administrator:'
|
13
|
+
)}
|
14
|
+
<br />
|
15
|
+
</span>
|
16
|
+
);
|
17
|
+
|
18
|
+
return (
|
19
|
+
<EmptyState
|
20
|
+
iconType="fa"
|
21
|
+
icon="lock"
|
22
|
+
header={__('Permission Denied')}
|
23
|
+
description={description}
|
24
|
+
documentation={props.doc}
|
25
|
+
/>
|
26
|
+
);
|
27
|
+
};
|
28
|
+
|
29
|
+
PermissionDenied.propTypes = {
|
30
|
+
doc: PropTypes.node.isRequired,
|
31
|
+
};
|
32
|
+
|
33
|
+
export default PermissionDenied;
|
@@ -0,0 +1,61 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { isEmpty } from 'lodash';
|
3
|
+
import PropTypes from 'prop-types';
|
4
|
+
|
5
|
+
import EmptySyncResult from './components/EmptySyncResult';
|
6
|
+
import FinishedSyncResult from './components/FinishedSyncResult';
|
7
|
+
|
8
|
+
import './TemplateSyncResult.scss';
|
9
|
+
|
10
|
+
const TemplateSyncResult = ({
|
11
|
+
syncResult: { templates, resultAction, repo, branch, gitUser, pagination },
|
12
|
+
history,
|
13
|
+
syncedTemplatesPageChange,
|
14
|
+
editPaths,
|
15
|
+
fileRepoStartWith,
|
16
|
+
}) => {
|
17
|
+
const redirectBack = () => history.push({ pathname: '/template_syncs' });
|
18
|
+
|
19
|
+
return isEmpty(templates) ? (
|
20
|
+
<EmptySyncResult primaryAction={redirectBack} />
|
21
|
+
) : (
|
22
|
+
<FinishedSyncResult
|
23
|
+
templates={templates}
|
24
|
+
type={resultAction}
|
25
|
+
repo={repo}
|
26
|
+
branch={branch}
|
27
|
+
gitUser={gitUser}
|
28
|
+
fileRepoStartWith={fileRepoStartWith}
|
29
|
+
editPaths={editPaths}
|
30
|
+
pagination={pagination}
|
31
|
+
pageChange={syncedTemplatesPageChange}
|
32
|
+
/>
|
33
|
+
);
|
34
|
+
};
|
35
|
+
|
36
|
+
TemplateSyncResult.propTypes = {
|
37
|
+
syncResult: PropTypes.shape({
|
38
|
+
templates: PropTypes.array,
|
39
|
+
resultAction: PropTypes.string,
|
40
|
+
repo: PropTypes.string,
|
41
|
+
branch: PropTypes.string,
|
42
|
+
gitUser: PropTypes.string,
|
43
|
+
pagination: PropTypes.shape({
|
44
|
+
page: PropTypes.number,
|
45
|
+
perPage: PropTypes.number,
|
46
|
+
}),
|
47
|
+
syncedTemplatesPageChange: PropTypes.func,
|
48
|
+
}).isRequired,
|
49
|
+
history: PropTypes.object.isRequired,
|
50
|
+
editPaths: PropTypes.object,
|
51
|
+
fileRepoStartWith: PropTypes.array,
|
52
|
+
syncedTemplatesPageChange: PropTypes.func,
|
53
|
+
};
|
54
|
+
|
55
|
+
TemplateSyncResult.defaultProps = {
|
56
|
+
editPaths: {},
|
57
|
+
syncedTemplatesPageChange: () => {},
|
58
|
+
fileRepoStartWith: [],
|
59
|
+
};
|
60
|
+
|
61
|
+
export default TemplateSyncResult;
|
@@ -0,0 +1,39 @@
|
|
1
|
+
#foreman-templates {
|
2
|
+
.list-view-pf-body {
|
3
|
+
.list-view-pf-description {
|
4
|
+
width: 20%;
|
5
|
+
}
|
6
|
+
}
|
7
|
+
|
8
|
+
.list-view-pf-additional-info-item.additional-info-wide {
|
9
|
+
width: 15%;
|
10
|
+
}
|
11
|
+
|
12
|
+
.list-group-item-heading {
|
13
|
+
font-weight: normal;
|
14
|
+
font-size: 12px;
|
15
|
+
}
|
16
|
+
|
17
|
+
.list-view-header {
|
18
|
+
border-top: 0px;
|
19
|
+
background-color: #fff;
|
20
|
+
border-left-color: #fff;
|
21
|
+
border-right-color: #fff;
|
22
|
+
|
23
|
+
.list-view-pf-main-info {
|
24
|
+
padding-bottom: 0px;
|
25
|
+
}
|
26
|
+
|
27
|
+
.list-group-item-heading {
|
28
|
+
font-weight: 600;
|
29
|
+
}
|
30
|
+
|
31
|
+
.list-view-pf-left {
|
32
|
+
visibility: hidden;
|
33
|
+
}
|
34
|
+
.list-view-pf-expand {
|
35
|
+
visibility: hidden;
|
36
|
+
margin-bottom: 0px;
|
37
|
+
}
|
38
|
+
}
|
39
|
+
}
|
@@ -0,0 +1,33 @@
|
|
1
|
+
import Immutable from 'seamless-immutable';
|
2
|
+
import { deepPropsToCamelCase } from 'foremanReact/common/helpers';
|
3
|
+
|
4
|
+
import {
|
5
|
+
TEMPLATESYNC_FORM_SUBMITTED,
|
6
|
+
SYNC_RESULT_PAGINATION_CHANGE,
|
7
|
+
} from '../../consts';
|
8
|
+
|
9
|
+
export const initialState = Immutable({
|
10
|
+
resultAction: '',
|
11
|
+
templates: [],
|
12
|
+
|
13
|
+
pagination: {
|
14
|
+
page: 1,
|
15
|
+
perPage: 20,
|
16
|
+
},
|
17
|
+
});
|
18
|
+
|
19
|
+
const syncResult = (state = initialState, action) => {
|
20
|
+
const { payload } = action;
|
21
|
+
switch (action.type) {
|
22
|
+
case TEMPLATESYNC_FORM_SUBMITTED:
|
23
|
+
return state.merge({
|
24
|
+
...deepPropsToCamelCase(payload.data),
|
25
|
+
});
|
26
|
+
case SYNC_RESULT_PAGINATION_CHANGE:
|
27
|
+
return state.set('pagination', payload.pagination);
|
28
|
+
default:
|
29
|
+
return state;
|
30
|
+
}
|
31
|
+
};
|
32
|
+
|
33
|
+
export default syncResult;
|
@@ -0,0 +1 @@
|
|
1
|
+
export const selectSyncResult = state => state.foremanTemplates.syncResult;
|
@@ -0,0 +1,86 @@
|
|
1
|
+
export const exportTemplates = [
|
2
|
+
{
|
3
|
+
name: 'random template',
|
4
|
+
templateFile: 'random_template.erb',
|
5
|
+
additionalErrors: null,
|
6
|
+
errors: {},
|
7
|
+
snippet: true,
|
8
|
+
locked: true,
|
9
|
+
className: 'JobTemplate',
|
10
|
+
humanizedClassName: 'Job Template',
|
11
|
+
},
|
12
|
+
{
|
13
|
+
name: 'CoreOS default',
|
14
|
+
templateFile: 'coreos_default.erb',
|
15
|
+
additionalErrors: null,
|
16
|
+
errors: {},
|
17
|
+
snippet: false,
|
18
|
+
locked: false,
|
19
|
+
className: 'Ptable',
|
20
|
+
humanizedClassName: 'Ptable',
|
21
|
+
},
|
22
|
+
];
|
23
|
+
|
24
|
+
export const noName = {
|
25
|
+
name: null,
|
26
|
+
templateFile: 'random_template.erb',
|
27
|
+
additionalErrors: 'No "name" found in metadata',
|
28
|
+
errors: null,
|
29
|
+
};
|
30
|
+
|
31
|
+
export const epel = {
|
32
|
+
name: 'EPEL',
|
33
|
+
templateFile: 'epel.erb',
|
34
|
+
additionalErrors: null,
|
35
|
+
errors: { base: ['This template is locked'] },
|
36
|
+
snippet: true,
|
37
|
+
locked: true,
|
38
|
+
className: 'ProvisioningTemplate',
|
39
|
+
kind: 'Provision',
|
40
|
+
humanizedClassName: 'Provisioning Template',
|
41
|
+
};
|
42
|
+
|
43
|
+
export const coreos = {
|
44
|
+
name: 'CoreOS default',
|
45
|
+
templateFile: 'coreos_default.erb',
|
46
|
+
additionalErrors: null,
|
47
|
+
errors: {},
|
48
|
+
snippet: false,
|
49
|
+
locked: false,
|
50
|
+
className: 'Ptable',
|
51
|
+
humanizedClassName: 'Ptable',
|
52
|
+
};
|
53
|
+
|
54
|
+
export const filteredOut = {
|
55
|
+
name: 'CoreOS default',
|
56
|
+
templateFile: 'coreos_default.erb',
|
57
|
+
additionalErrors: null,
|
58
|
+
additionalInfo: 'Skipping, this template was filtered out.',
|
59
|
+
errors: {},
|
60
|
+
snippet: false,
|
61
|
+
locked: false,
|
62
|
+
className: 'Ptable',
|
63
|
+
humanizedClassName: 'Ptable',
|
64
|
+
};
|
65
|
+
|
66
|
+
export const importTemplates = [
|
67
|
+
noName,
|
68
|
+
epel,
|
69
|
+
coreos,
|
70
|
+
{
|
71
|
+
name: null,
|
72
|
+
templateFile: 'no_model.erb',
|
73
|
+
additionalErrors: 'No "model" found in metadata',
|
74
|
+
errors: null,
|
75
|
+
},
|
76
|
+
{
|
77
|
+
name: 'Kickstart fake',
|
78
|
+
templateFile: 'kickstart_fake.erb',
|
79
|
+
additionalErrors: null,
|
80
|
+
errors: { name: ['has already been taken'] },
|
81
|
+
snippet: true,
|
82
|
+
locked: true,
|
83
|
+
className: 'ProvisioningTemplate',
|
84
|
+
humanizedClassName: 'Provisioning Template',
|
85
|
+
},
|
86
|
+
];
|