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,37 @@
|
|
1
|
+
import { testComponentSnapshotsWithFixtures } from 'react-redux-test-utils';
|
2
|
+
|
3
|
+
import {
|
4
|
+
importTemplates,
|
5
|
+
exportTemplates,
|
6
|
+
} from '../__fixtures__/templateSyncResult.fixtures';
|
7
|
+
import TemplateSyncResult from '../TemplateSyncResult';
|
8
|
+
|
9
|
+
const fixtures = {
|
10
|
+
'should render export result': {
|
11
|
+
syncResult: {
|
12
|
+
resultAction: 'export',
|
13
|
+
templates: exportTemplates,
|
14
|
+
repo: 'https://github.com/theforeman/community-templates.git',
|
15
|
+
branch: 'master',
|
16
|
+
gitUser: 'Admin',
|
17
|
+
},
|
18
|
+
history: {},
|
19
|
+
},
|
20
|
+
'should render empty state when no templates synced': {
|
21
|
+
syncResult: {
|
22
|
+
templates: [],
|
23
|
+
},
|
24
|
+
history: {},
|
25
|
+
},
|
26
|
+
'should render import result': {
|
27
|
+
syncResult: {
|
28
|
+
resultAction: 'import',
|
29
|
+
templates: importTemplates,
|
30
|
+
repo: '/home/vagrant/templates',
|
31
|
+
},
|
32
|
+
history: {},
|
33
|
+
},
|
34
|
+
};
|
35
|
+
|
36
|
+
describe('TemplateSyncResult', () =>
|
37
|
+
testComponentSnapshotsWithFixtures(TemplateSyncResult, fixtures));
|
@@ -0,0 +1,48 @@
|
|
1
|
+
import { testReducerSnapshotWithFixtures } from 'react-redux-test-utils';
|
2
|
+
|
3
|
+
import reducer, { initialState } from '../TemplateSyncResultReducer';
|
4
|
+
import { importTemplates } from '../__fixtures__/templateSyncResult.fixtures';
|
5
|
+
|
6
|
+
import {
|
7
|
+
TEMPLATESYNC_FORM_SUBMITTED,
|
8
|
+
SYNC_RESULT_PAGINATION_CHANGE,
|
9
|
+
} from '../../../consts';
|
10
|
+
|
11
|
+
const fixtures = {
|
12
|
+
'should return initial state': {
|
13
|
+
state: initialState,
|
14
|
+
action: {
|
15
|
+
type: undefined,
|
16
|
+
payload: {},
|
17
|
+
},
|
18
|
+
},
|
19
|
+
'should set new pagination': {
|
20
|
+
state: initialState,
|
21
|
+
action: {
|
22
|
+
type: SYNC_RESULT_PAGINATION_CHANGE,
|
23
|
+
payload: {
|
24
|
+
pagination: {
|
25
|
+
page: 2,
|
26
|
+
perPage: 5,
|
27
|
+
},
|
28
|
+
},
|
29
|
+
},
|
30
|
+
},
|
31
|
+
'should update state when form submitted': {
|
32
|
+
state: initialState,
|
33
|
+
action: {
|
34
|
+
type: TEMPLATESYNC_FORM_SUBMITTED,
|
35
|
+
payload: {
|
36
|
+
data: {
|
37
|
+
templates: importTemplates,
|
38
|
+
repo: 'https://github.com/theforeman/community-templates.git',
|
39
|
+
branch: 'master',
|
40
|
+
result_action: 'import',
|
41
|
+
},
|
42
|
+
},
|
43
|
+
},
|
44
|
+
},
|
45
|
+
};
|
46
|
+
|
47
|
+
describe('TemplateSyncResultReducer', () =>
|
48
|
+
testReducerSnapshotWithFixtures(reducer, fixtures));
|
data/webpack/components/TemplateSyncResult/__tests__/__snapshots__/TemplateSyncResult.test.js.snap
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
2
|
+
|
3
|
+
exports[`TemplateSyncResult should render empty state when no templates synced 1`] = `
|
4
|
+
<EmptySyncResult
|
5
|
+
primaryAction={[Function]}
|
6
|
+
/>
|
7
|
+
`;
|
8
|
+
|
9
|
+
exports[`TemplateSyncResult should render export result 1`] = `
|
10
|
+
<FinishedSyncResult
|
11
|
+
branch="master"
|
12
|
+
editPaths={Object {}}
|
13
|
+
fileRepoStartWith={Array []}
|
14
|
+
gitUser="Admin"
|
15
|
+
pageChange={[Function]}
|
16
|
+
pagination={Object {}}
|
17
|
+
repo="https://github.com/theforeman/community-templates.git"
|
18
|
+
templates={
|
19
|
+
Array [
|
20
|
+
Object {
|
21
|
+
"additionalErrors": null,
|
22
|
+
"className": "JobTemplate",
|
23
|
+
"errors": Object {},
|
24
|
+
"humanizedClassName": "Job Template",
|
25
|
+
"locked": true,
|
26
|
+
"name": "random template",
|
27
|
+
"snippet": true,
|
28
|
+
"templateFile": "random_template.erb",
|
29
|
+
},
|
30
|
+
Object {
|
31
|
+
"additionalErrors": null,
|
32
|
+
"className": "Ptable",
|
33
|
+
"errors": Object {},
|
34
|
+
"humanizedClassName": "Ptable",
|
35
|
+
"locked": false,
|
36
|
+
"name": "CoreOS default",
|
37
|
+
"snippet": false,
|
38
|
+
"templateFile": "coreos_default.erb",
|
39
|
+
},
|
40
|
+
]
|
41
|
+
}
|
42
|
+
type="export"
|
43
|
+
/>
|
44
|
+
`;
|
45
|
+
|
46
|
+
exports[`TemplateSyncResult should render import result 1`] = `
|
47
|
+
<FinishedSyncResult
|
48
|
+
branch=""
|
49
|
+
editPaths={Object {}}
|
50
|
+
fileRepoStartWith={Array []}
|
51
|
+
gitUser=""
|
52
|
+
pageChange={[Function]}
|
53
|
+
pagination={Object {}}
|
54
|
+
repo="/home/vagrant/templates"
|
55
|
+
templates={
|
56
|
+
Array [
|
57
|
+
Object {
|
58
|
+
"additionalErrors": "No \\"name\\" found in metadata",
|
59
|
+
"errors": null,
|
60
|
+
"name": null,
|
61
|
+
"templateFile": "random_template.erb",
|
62
|
+
},
|
63
|
+
Object {
|
64
|
+
"additionalErrors": null,
|
65
|
+
"className": "ProvisioningTemplate",
|
66
|
+
"errors": Object {
|
67
|
+
"base": Array [
|
68
|
+
"This template is locked",
|
69
|
+
],
|
70
|
+
},
|
71
|
+
"humanizedClassName": "Provisioning Template",
|
72
|
+
"kind": "Provision",
|
73
|
+
"locked": true,
|
74
|
+
"name": "EPEL",
|
75
|
+
"snippet": true,
|
76
|
+
"templateFile": "epel.erb",
|
77
|
+
},
|
78
|
+
Object {
|
79
|
+
"additionalErrors": null,
|
80
|
+
"className": "Ptable",
|
81
|
+
"errors": Object {},
|
82
|
+
"humanizedClassName": "Ptable",
|
83
|
+
"locked": false,
|
84
|
+
"name": "CoreOS default",
|
85
|
+
"snippet": false,
|
86
|
+
"templateFile": "coreos_default.erb",
|
87
|
+
},
|
88
|
+
Object {
|
89
|
+
"additionalErrors": "No \\"model\\" found in metadata",
|
90
|
+
"errors": null,
|
91
|
+
"name": null,
|
92
|
+
"templateFile": "no_model.erb",
|
93
|
+
},
|
94
|
+
Object {
|
95
|
+
"additionalErrors": null,
|
96
|
+
"className": "ProvisioningTemplate",
|
97
|
+
"errors": Object {
|
98
|
+
"name": Array [
|
99
|
+
"has already been taken",
|
100
|
+
],
|
101
|
+
},
|
102
|
+
"humanizedClassName": "Provisioning Template",
|
103
|
+
"locked": true,
|
104
|
+
"name": "Kickstart fake",
|
105
|
+
"snippet": true,
|
106
|
+
"templateFile": "kickstart_fake.erb",
|
107
|
+
},
|
108
|
+
]
|
109
|
+
}
|
110
|
+
type="import"
|
111
|
+
/>
|
112
|
+
`;
|
@@ -0,0 +1,88 @@
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
2
|
+
|
3
|
+
exports[`TemplateSyncResultReducer should return initial state 1`] = `
|
4
|
+
Object {
|
5
|
+
"pagination": Object {
|
6
|
+
"page": 1,
|
7
|
+
"perPage": 20,
|
8
|
+
},
|
9
|
+
"resultAction": "",
|
10
|
+
"templates": Array [],
|
11
|
+
}
|
12
|
+
`;
|
13
|
+
|
14
|
+
exports[`TemplateSyncResultReducer should set new pagination 1`] = `
|
15
|
+
Object {
|
16
|
+
"pagination": Object {
|
17
|
+
"page": 2,
|
18
|
+
"perPage": 5,
|
19
|
+
},
|
20
|
+
"resultAction": "",
|
21
|
+
"templates": Array [],
|
22
|
+
}
|
23
|
+
`;
|
24
|
+
|
25
|
+
exports[`TemplateSyncResultReducer should update state when form submitted 1`] = `
|
26
|
+
Object {
|
27
|
+
"branch": "master",
|
28
|
+
"pagination": Object {
|
29
|
+
"page": 1,
|
30
|
+
"perPage": 20,
|
31
|
+
},
|
32
|
+
"repo": "https://github.com/theforeman/community-templates.git",
|
33
|
+
"resultAction": "import",
|
34
|
+
"templates": Array [
|
35
|
+
Object {
|
36
|
+
"additionalErrors": "No \\"name\\" found in metadata",
|
37
|
+
"errors": null,
|
38
|
+
"name": null,
|
39
|
+
"templateFile": "random_template.erb",
|
40
|
+
},
|
41
|
+
Object {
|
42
|
+
"additionalErrors": null,
|
43
|
+
"className": "ProvisioningTemplate",
|
44
|
+
"errors": Object {
|
45
|
+
"base": Array [
|
46
|
+
"This template is locked",
|
47
|
+
],
|
48
|
+
},
|
49
|
+
"humanizedClassName": "Provisioning Template",
|
50
|
+
"kind": "Provision",
|
51
|
+
"locked": true,
|
52
|
+
"name": "EPEL",
|
53
|
+
"snippet": true,
|
54
|
+
"templateFile": "epel.erb",
|
55
|
+
},
|
56
|
+
Object {
|
57
|
+
"additionalErrors": null,
|
58
|
+
"className": "Ptable",
|
59
|
+
"errors": Object {},
|
60
|
+
"humanizedClassName": "Ptable",
|
61
|
+
"locked": false,
|
62
|
+
"name": "CoreOS default",
|
63
|
+
"snippet": false,
|
64
|
+
"templateFile": "coreos_default.erb",
|
65
|
+
},
|
66
|
+
Object {
|
67
|
+
"additionalErrors": "No \\"model\\" found in metadata",
|
68
|
+
"errors": null,
|
69
|
+
"name": null,
|
70
|
+
"templateFile": "no_model.erb",
|
71
|
+
},
|
72
|
+
Object {
|
73
|
+
"additionalErrors": null,
|
74
|
+
"className": "ProvisioningTemplate",
|
75
|
+
"errors": Object {
|
76
|
+
"name": Array [
|
77
|
+
"has already been taken",
|
78
|
+
],
|
79
|
+
},
|
80
|
+
"humanizedClassName": "Provisioning Template",
|
81
|
+
"locked": true,
|
82
|
+
"name": "Kickstart fake",
|
83
|
+
"snippet": true,
|
84
|
+
"templateFile": "kickstart_fake.erb",
|
85
|
+
},
|
86
|
+
],
|
87
|
+
}
|
88
|
+
`;
|
@@ -0,0 +1,25 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { EmptyState, Button } from 'patternfly-react';
|
3
|
+
import PropTypes from 'prop-types';
|
4
|
+
|
5
|
+
const EmptySyncResult = ({ primaryAction }) => (
|
6
|
+
<EmptyState>
|
7
|
+
<EmptyState.Icon type="fa" name="refresh" />
|
8
|
+
<EmptyState.Title>No Template Sync Result</EmptyState.Title>
|
9
|
+
<EmptyState.Info>
|
10
|
+
To view results of a template sync, you must import/export the templates
|
11
|
+
first.
|
12
|
+
</EmptyState.Info>
|
13
|
+
<EmptyState.Action>
|
14
|
+
<Button bsStyle="primary" bsSize="large" onClick={primaryAction}>
|
15
|
+
Sync Templates
|
16
|
+
</Button>
|
17
|
+
</EmptyState.Action>
|
18
|
+
</EmptyState>
|
19
|
+
);
|
20
|
+
|
21
|
+
EmptySyncResult.propTypes = {
|
22
|
+
primaryAction: PropTypes.func.isRequired,
|
23
|
+
};
|
24
|
+
|
25
|
+
export default EmptySyncResult;
|
@@ -0,0 +1,77 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import PropTypes from 'prop-types';
|
3
|
+
import { capitalize } from 'lodash';
|
4
|
+
|
5
|
+
import PageLayout from 'foremanReact/routes/common/PageLayout/PageLayout';
|
6
|
+
import { LinkContainer } from 'react-router-bootstrap';
|
7
|
+
|
8
|
+
import { Button } from 'patternfly-react';
|
9
|
+
import SyncResultList from './SyncResultList';
|
10
|
+
|
11
|
+
const titleString = (type, repo, branch, gitUser, fileRepoStartWith) => {
|
12
|
+
const prep = type === 'import' ? 'from' : 'to';
|
13
|
+
const isFileRepo = fileRepoStartWith.reduce(
|
14
|
+
(memo, item) => repo.startsWith(item) || memo,
|
15
|
+
false
|
16
|
+
);
|
17
|
+
|
18
|
+
const branchString = branch && !isFileRepo ? `and branch ${branch}` : '';
|
19
|
+
const userString = (gitUser && `as user ${gitUser}`) || '';
|
20
|
+
|
21
|
+
return `${capitalize(type)} ${prep} ${repo} ${branchString} ${userString}`;
|
22
|
+
};
|
23
|
+
|
24
|
+
const FinishedSyncResult = ({
|
25
|
+
templates,
|
26
|
+
type,
|
27
|
+
repo,
|
28
|
+
branch,
|
29
|
+
gitUser,
|
30
|
+
fileRepoStartWith,
|
31
|
+
pagination,
|
32
|
+
pageChange,
|
33
|
+
editPaths,
|
34
|
+
}) => (
|
35
|
+
<PageLayout
|
36
|
+
searchable={false}
|
37
|
+
header={titleString(type, repo, branch, gitUser, fileRepoStartWith)}
|
38
|
+
>
|
39
|
+
<div className="row">
|
40
|
+
<div className="title-filter col-md-4"> </div>
|
41
|
+
<div id="title_action" className="col-md-8">
|
42
|
+
<div className="btn-toolbar pull-right">
|
43
|
+
<LinkContainer to="/template_syncs" activeClassName="">
|
44
|
+
<Button>{__('Back to sync form')}</Button>
|
45
|
+
</LinkContainer>
|
46
|
+
</div>
|
47
|
+
</div>
|
48
|
+
</div>
|
49
|
+
|
50
|
+
<SyncResultList
|
51
|
+
templates={templates}
|
52
|
+
pagination={pagination}
|
53
|
+
editPaths={editPaths}
|
54
|
+
pageChange={pageChange}
|
55
|
+
/>
|
56
|
+
</PageLayout>
|
57
|
+
);
|
58
|
+
|
59
|
+
FinishedSyncResult.propTypes = {
|
60
|
+
templates: PropTypes.array.isRequired,
|
61
|
+
type: PropTypes.string.isRequired,
|
62
|
+
repo: PropTypes.string.isRequired,
|
63
|
+
branch: PropTypes.string,
|
64
|
+
gitUser: PropTypes.string,
|
65
|
+
pagination: PropTypes.object,
|
66
|
+
pageChange: PropTypes.func.isRequired,
|
67
|
+
editPaths: PropTypes.object.isRequired,
|
68
|
+
fileRepoStartWith: PropTypes.array.isRequired,
|
69
|
+
};
|
70
|
+
|
71
|
+
FinishedSyncResult.defaultProps = {
|
72
|
+
branch: '',
|
73
|
+
gitUser: '',
|
74
|
+
pagination: {},
|
75
|
+
};
|
76
|
+
|
77
|
+
export default FinishedSyncResult;
|
@@ -0,0 +1,38 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { ListView, Icon } from 'patternfly-react';
|
3
|
+
import classNames from 'classnames';
|
4
|
+
|
5
|
+
import InfoItem from './SyncedTemplate/InfoItem';
|
6
|
+
|
7
|
+
const ListViewHeader = props => {
|
8
|
+
const additionalInfo = [
|
9
|
+
'Name',
|
10
|
+
'Locked',
|
11
|
+
'Snippet',
|
12
|
+
'Template Class',
|
13
|
+
'Kind',
|
14
|
+
'File Name',
|
15
|
+
].map((title, idx) => (
|
16
|
+
<InfoItem itemId={`${idx}`} key={idx}>
|
17
|
+
<strong>{title}</strong>
|
18
|
+
</InfoItem>
|
19
|
+
));
|
20
|
+
|
21
|
+
// Use ListView.Item as a header to get a vertical alignment
|
22
|
+
return (
|
23
|
+
<ListView.Item
|
24
|
+
additionalInfo={additionalInfo}
|
25
|
+
className={classNames(
|
26
|
+
'listViewItem--listItemVariants',
|
27
|
+
'list-view-header'
|
28
|
+
)}
|
29
|
+
leftContent={<Icon name="ok" size="sm" type="pf" />}
|
30
|
+
hideCloseIcon
|
31
|
+
stacked
|
32
|
+
>
|
33
|
+
<span />
|
34
|
+
</ListView.Item>
|
35
|
+
);
|
36
|
+
};
|
37
|
+
|
38
|
+
export default ListViewHeader;
|
@@ -0,0 +1,41 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { ListView } from 'patternfly-react';
|
3
|
+
import PropTypes from 'prop-types';
|
4
|
+
|
5
|
+
import Pagination from 'foremanReact/components/Pagination/PaginationWrapper';
|
6
|
+
|
7
|
+
import SyncedTemplate from './SyncedTemplate';
|
8
|
+
import { templatesPage } from '../TemplateSyncResultHelpers';
|
9
|
+
import ListViewHeader from './ListViewHeader';
|
10
|
+
|
11
|
+
const SyncResultList = ({ pagination, pageChange, templates, editPaths }) => (
|
12
|
+
<ListView>
|
13
|
+
<ListViewHeader />
|
14
|
+
{templatesPage(templates, pagination).map(template => (
|
15
|
+
<SyncedTemplate
|
16
|
+
template={template}
|
17
|
+
key={template.name}
|
18
|
+
editPath={editPaths[template.className]}
|
19
|
+
/>
|
20
|
+
))}
|
21
|
+
<Pagination
|
22
|
+
viewType="list"
|
23
|
+
itemCount={templates.length}
|
24
|
+
pagination={pagination}
|
25
|
+
onChange={pageChange}
|
26
|
+
dropdownButtonId="template-sync-result-dropdown"
|
27
|
+
/>
|
28
|
+
</ListView>
|
29
|
+
);
|
30
|
+
|
31
|
+
SyncResultList.propTypes = {
|
32
|
+
pagination: PropTypes.shape({
|
33
|
+
page: PropTypes.number,
|
34
|
+
perPage: PropTypes.number,
|
35
|
+
}).isRequired,
|
36
|
+
pageChange: PropTypes.func.isRequired,
|
37
|
+
templates: PropTypes.array.isRequired,
|
38
|
+
editPaths: PropTypes.object.isRequired,
|
39
|
+
};
|
40
|
+
|
41
|
+
export default SyncResultList;
|
@@ -0,0 +1,16 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import PropTypes from 'prop-types';
|
3
|
+
|
4
|
+
import InfoItem from './InfoItem';
|
5
|
+
import { itemIteratorId } from './helpers';
|
6
|
+
|
7
|
+
const EmptyInfoItem = ({ template, attr }) => (
|
8
|
+
<InfoItem itemId={itemIteratorId(template, attr)} />
|
9
|
+
);
|
10
|
+
|
11
|
+
EmptyInfoItem.propTypes = {
|
12
|
+
template: PropTypes.object.isRequired,
|
13
|
+
attr: PropTypes.string.isRequired,
|
14
|
+
};
|
15
|
+
|
16
|
+
export default EmptyInfoItem;
|
@@ -0,0 +1,21 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { Icon } from 'patternfly-react';
|
3
|
+
import PropTypes from 'prop-types';
|
4
|
+
|
5
|
+
import InfoItem from './InfoItem';
|
6
|
+
import { itemIteratorId } from './helpers';
|
7
|
+
|
8
|
+
const IconInfoItem = ({ template, attr, iconName, tooltipText }) => (
|
9
|
+
<InfoItem itemId={itemIteratorId(template, attr)} tooltipText={tooltipText}>
|
10
|
+
<Icon type="fa" name={iconName} />
|
11
|
+
</InfoItem>
|
12
|
+
);
|
13
|
+
|
14
|
+
IconInfoItem.propTypes = {
|
15
|
+
template: PropTypes.object.isRequired,
|
16
|
+
attr: PropTypes.string.isRequired,
|
17
|
+
iconName: PropTypes.string.isRequired,
|
18
|
+
tooltipText: PropTypes.string.isRequired,
|
19
|
+
};
|
20
|
+
|
21
|
+
export default IconInfoItem;
|
@@ -0,0 +1,34 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { ListView, OverlayTrigger, Tooltip } from 'patternfly-react';
|
3
|
+
import PropTypes from 'prop-types';
|
4
|
+
|
5
|
+
const InfoItem = ({ itemId, children, tooltipText }) => {
|
6
|
+
const overlay = (
|
7
|
+
<OverlayTrigger
|
8
|
+
overlay={tooltipText ? <Tooltip id={itemId}>{tooltipText}</Tooltip> : ''}
|
9
|
+
placement="top"
|
10
|
+
trigger={['hover', 'focus']}
|
11
|
+
rootClose={false}
|
12
|
+
>
|
13
|
+
{children}
|
14
|
+
</OverlayTrigger>
|
15
|
+
);
|
16
|
+
return (
|
17
|
+
<ListView.InfoItem key={itemId} className="additional-info-wide">
|
18
|
+
{tooltipText ? overlay : children}
|
19
|
+
</ListView.InfoItem>
|
20
|
+
);
|
21
|
+
};
|
22
|
+
|
23
|
+
InfoItem.propTypes = {
|
24
|
+
itemId: PropTypes.string.isRequired,
|
25
|
+
children: PropTypes.node,
|
26
|
+
tooltipText: PropTypes.string,
|
27
|
+
};
|
28
|
+
|
29
|
+
InfoItem.defaultProps = {
|
30
|
+
tooltipText: '',
|
31
|
+
children: undefined,
|
32
|
+
};
|
33
|
+
|
34
|
+
export default InfoItem;
|
@@ -0,0 +1,37 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { ListView } from 'patternfly-react';
|
3
|
+
import PropTypes from 'prop-types';
|
4
|
+
|
5
|
+
import { itemIteratorId } from './helpers';
|
6
|
+
|
7
|
+
const wrapWithLink = (template, editPath) => {
|
8
|
+
if (template.id && template.canEdit) {
|
9
|
+
return (
|
10
|
+
<a
|
11
|
+
href={editPath.replace(':id', template.id)}
|
12
|
+
target="_blank"
|
13
|
+
rel="noopener noreferrer"
|
14
|
+
>
|
15
|
+
{template.name}
|
16
|
+
</a>
|
17
|
+
);
|
18
|
+
}
|
19
|
+
return template.name || ' ';
|
20
|
+
};
|
21
|
+
|
22
|
+
const LinkInfoItem = ({ template, editPath, attr }) => (
|
23
|
+
<ListView.InfoItem
|
24
|
+
key={itemIteratorId(template, attr)}
|
25
|
+
className="additional-info-wide"
|
26
|
+
>
|
27
|
+
{wrapWithLink(template, editPath)}
|
28
|
+
</ListView.InfoItem>
|
29
|
+
);
|
30
|
+
|
31
|
+
LinkInfoItem.propTypes = {
|
32
|
+
template: PropTypes.object.isRequired,
|
33
|
+
editPath: PropTypes.string.isRequired,
|
34
|
+
attr: PropTypes.string.isRequired,
|
35
|
+
};
|
36
|
+
|
37
|
+
export default LinkInfoItem;
|
@@ -0,0 +1,50 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import EllipsisWithTooltip from 'react-ellipsis-with-tooltip';
|
3
|
+
import PropTypes from 'prop-types';
|
4
|
+
|
5
|
+
import InfoItem from './InfoItem';
|
6
|
+
import { itemIteratorId } from './helpers';
|
7
|
+
|
8
|
+
const StringInfoItem = ({
|
9
|
+
template,
|
10
|
+
attr,
|
11
|
+
tooltipText,
|
12
|
+
translate,
|
13
|
+
mapAttr,
|
14
|
+
elipsed,
|
15
|
+
}) => {
|
16
|
+
const inner = (
|
17
|
+
<span>
|
18
|
+
{translate ? __(mapAttr(template, attr)) : mapAttr(template, attr)}
|
19
|
+
</span>
|
20
|
+
);
|
21
|
+
const innerContent = elipsed ? (
|
22
|
+
<EllipsisWithTooltip placement="top">{inner}</EllipsisWithTooltip>
|
23
|
+
) : (
|
24
|
+
inner
|
25
|
+
);
|
26
|
+
|
27
|
+
return (
|
28
|
+
<InfoItem itemId={itemIteratorId(template, attr)} tooltipText={tooltipText}>
|
29
|
+
{innerContent}
|
30
|
+
</InfoItem>
|
31
|
+
);
|
32
|
+
};
|
33
|
+
|
34
|
+
StringInfoItem.propTypes = {
|
35
|
+
template: PropTypes.object.isRequired,
|
36
|
+
attr: PropTypes.string.isRequired,
|
37
|
+
tooltipText: PropTypes.string,
|
38
|
+
translate: PropTypes.bool,
|
39
|
+
mapAttr: PropTypes.func,
|
40
|
+
elipsed: PropTypes.bool,
|
41
|
+
};
|
42
|
+
|
43
|
+
StringInfoItem.defaultProps = {
|
44
|
+
translate: false,
|
45
|
+
mapAttr: (template, attr) => template[attr],
|
46
|
+
elipsed: false,
|
47
|
+
tooltipText: undefined,
|
48
|
+
};
|
49
|
+
|
50
|
+
export default StringInfoItem;
|