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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 799e5dc7d9045fbb1bcb6571584f705e3965c324
|
4
|
+
data.tar.gz: 71e4088ec73d0f103ee812952acbe2333264eebc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 89b63e0f1f73daed9c3cdfd1d78092d6733656169370cf976590099c4263972ed274c1c9a5dddf7eb629b0b9e61207434f7bfb94664b5e62171e1e4f219c1295
|
7
|
+
data.tar.gz: 0ce7b7cd05ecbd305a16444d80e57ecc85251eff82d0eec8d36f29f49f311203308171831fb807461bed587f64635fc5c088dfa14abafbd7458cd2e5f9557236
|
data/.babelrc
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
{
|
2
|
+
"presets": ["env", "react"],
|
3
|
+
"plugins": [
|
4
|
+
"transform-class-properties",
|
5
|
+
"transform-object-rest-spread",
|
6
|
+
"transform-object-assign"
|
7
|
+
],
|
8
|
+
"env": {
|
9
|
+
"test": {
|
10
|
+
"presets": ["@theforeman/vendor-dev/babel.preset.js"]
|
11
|
+
},
|
12
|
+
"storybook": {
|
13
|
+
"presets": ["@theforeman/vendor-dev/babel.preset.js"]
|
14
|
+
}
|
15
|
+
}
|
16
|
+
}
|
data/package.json
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
{
|
2
|
+
"name": "foreman_templates",
|
3
|
+
"version": "0.0.1",
|
4
|
+
"description": "This plugin will sync the contents of the Foreman Community Templates [repository](https://github.com/theforeman/community-templates/) (or a git repo of your choice) to your local Foreman instance",
|
5
|
+
"main": "index.js",
|
6
|
+
"directories": {
|
7
|
+
"test": "test"
|
8
|
+
},
|
9
|
+
"scripts": {
|
10
|
+
"test": "node node_modules/.bin/jest webpack",
|
11
|
+
"lint": "./node_modules/.bin/eslint -c .eslintrc webpack/"
|
12
|
+
},
|
13
|
+
"repository": {
|
14
|
+
"type": "git",
|
15
|
+
"url": "git+https://github.com/theforeman/foreman_templates.git"
|
16
|
+
},
|
17
|
+
"author": "The Foreman team",
|
18
|
+
"license": "GPL-3.0",
|
19
|
+
"bugs": {
|
20
|
+
"url": "https://projects.theforeman.org"
|
21
|
+
},
|
22
|
+
"homepage": "https://github.com/theforeman/foreman_templates",
|
23
|
+
"dependencies": {
|
24
|
+
"@theforeman/vendor": "^1.7.0"
|
25
|
+
},
|
26
|
+
"devDependencies": {
|
27
|
+
"@theforeman/vendor-dev": "^1.7.0",
|
28
|
+
"babel-eslint": "^8.2.1",
|
29
|
+
"babel-plugin-transform-class-properties": "^6.24.1",
|
30
|
+
"babel-plugin-transform-object-assign": "^6.22.0",
|
31
|
+
"babel-plugin-transform-object-rest-spread": "^6.26.0",
|
32
|
+
"babel-preset-env": "^1.6.0",
|
33
|
+
"babel-preset-react": "^6.24.1",
|
34
|
+
"enzyme": "^3.7.0",
|
35
|
+
"enzyme-adapter-react-16": "^1.7.0",
|
36
|
+
"enzyme-to-json": "^3.3.5",
|
37
|
+
"eslint": "^4.18.1",
|
38
|
+
"eslint-config-airbnb": "^16.0.0",
|
39
|
+
"eslint-plugin-import": "^2.8.0",
|
40
|
+
"eslint-plugin-jest": "^21.2.0",
|
41
|
+
"eslint-plugin-jsx-a11y": "^6.0.2",
|
42
|
+
"eslint-plugin-patternfly-react": "^0.2.1",
|
43
|
+
"eslint-plugin-react": "^7.4.0",
|
44
|
+
"identity-obj-proxy": "^3.0.0",
|
45
|
+
"jest": "^23.6.0",
|
46
|
+
"prettier": "^1.16.4",
|
47
|
+
"react-redux-test-utils": "^0.1.1"
|
48
|
+
},
|
49
|
+
"jest": {
|
50
|
+
"verbose": true,
|
51
|
+
"moduleDirectories": [
|
52
|
+
"node_modules/@theforeman/vendor-core/node_modules",
|
53
|
+
"node_modules",
|
54
|
+
"webpack"
|
55
|
+
],
|
56
|
+
"setupFiles": [
|
57
|
+
"raf/polyfill",
|
58
|
+
"./webpack/testSetup.js"
|
59
|
+
],
|
60
|
+
"testPathIgnorePatterns": [
|
61
|
+
"/node_modules/",
|
62
|
+
"<rootDir>/foreman/"
|
63
|
+
],
|
64
|
+
"moduleNameMapper": {
|
65
|
+
"^.+\\.(css|scss)$": "identity-obj-proxy"
|
66
|
+
}
|
67
|
+
}
|
68
|
+
}
|
@@ -0,0 +1,29 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { BrowserRouter as Router } from 'react-router-dom';
|
3
|
+
import PropTypes from 'prop-types';
|
4
|
+
|
5
|
+
import Routes from './Routes';
|
6
|
+
|
7
|
+
const ForemanTemplates = ({ data }) => (
|
8
|
+
<Router>
|
9
|
+
<Routes
|
10
|
+
apiUrls={data.apiUrls}
|
11
|
+
validationData={data.validationData}
|
12
|
+
editPaths={data.editPaths}
|
13
|
+
fileRepoStartWith={data.fileRepoStartWith}
|
14
|
+
userPermissions={data.userPermissions}
|
15
|
+
/>
|
16
|
+
</Router>
|
17
|
+
);
|
18
|
+
|
19
|
+
ForemanTemplates.propTypes = {
|
20
|
+
data: PropTypes.shape({
|
21
|
+
apiUrls: PropTypes.object,
|
22
|
+
validationData: PropTypes.object,
|
23
|
+
editPaths: PropTypes.object,
|
24
|
+
userPermissions: PropTypes.object,
|
25
|
+
fileRepoStartWith: PropTypes.array,
|
26
|
+
}).isRequired,
|
27
|
+
};
|
28
|
+
|
29
|
+
export default ForemanTemplates;
|
data/webpack/Routes.js
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { Route, Switch } from 'react-router-dom';
|
3
|
+
|
4
|
+
import NewTemplateSync from './components/NewTemplateSync';
|
5
|
+
import TemplateSyncResult from './components/TemplateSyncResult';
|
6
|
+
import PageNotFound from './components/PageNotFound';
|
7
|
+
|
8
|
+
const links = [
|
9
|
+
{
|
10
|
+
title: 'New Template Sync',
|
11
|
+
path: 'template_syncs',
|
12
|
+
Component: NewTemplateSync,
|
13
|
+
},
|
14
|
+
{
|
15
|
+
title: 'Template Sync Result',
|
16
|
+
path: 'template_syncs/result',
|
17
|
+
Component: TemplateSyncResult,
|
18
|
+
},
|
19
|
+
];
|
20
|
+
|
21
|
+
export default data => (
|
22
|
+
<Switch>
|
23
|
+
{links.map(({ path, Component }) => (
|
24
|
+
<Route
|
25
|
+
exact
|
26
|
+
key={path}
|
27
|
+
path={`/${path}`}
|
28
|
+
render={props => <Component {...props} {...data} />}
|
29
|
+
/>
|
30
|
+
))}
|
31
|
+
<Route component={PageNotFound} />
|
32
|
+
</Switch>
|
33
|
+
);
|
@@ -0,0 +1,27 @@
|
|
1
|
+
import { camelCase } from 'lodash';
|
2
|
+
|
3
|
+
export const propsToCamelCase = ob =>
|
4
|
+
propsToCase(camelCase, 'propsToCamelCase only takes objects', ob);
|
5
|
+
|
6
|
+
export const deepPropsToCamelCase = obj => {
|
7
|
+
if (typeof obj !== 'object' || obj === null) {
|
8
|
+
return obj;
|
9
|
+
}
|
10
|
+
if (Array.isArray(obj)) {
|
11
|
+
return obj.map(deepPropsToCamelCase);
|
12
|
+
}
|
13
|
+
const transformed = propsToCamelCase(obj);
|
14
|
+
return Object.keys(transformed).reduce((memo, key) => {
|
15
|
+
memo[key] = deepPropsToCamelCase(transformed[key]);
|
16
|
+
return memo;
|
17
|
+
}, {});
|
18
|
+
};
|
19
|
+
|
20
|
+
const propsToCase = (casingFn, errorMsg, ob) => {
|
21
|
+
if (typeof ob !== 'object') throw Error(errorMsg);
|
22
|
+
|
23
|
+
return Object.keys(ob).reduce((memo, key) => {
|
24
|
+
memo[casingFn(key)] = ob[key];
|
25
|
+
return memo;
|
26
|
+
}, {});
|
27
|
+
};
|
@@ -0,0 +1 @@
|
|
1
|
+
export default {};
|
@@ -0,0 +1,17 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { testSelectorsSnapshotWithFixtures } from 'react-redux-test-utils';
|
3
|
+
import withProtectedView from '../withProtectedView';
|
4
|
+
|
5
|
+
const ProtectedComponent = () => <div>Protected component</div>;
|
6
|
+
|
7
|
+
const ProtectionComponent = () => <div>Protection component</div>;
|
8
|
+
|
9
|
+
const fixtures = {
|
10
|
+
'should return protected component': () =>
|
11
|
+
withProtectedView(ProtectedComponent, ProtectionComponent, () => true)(),
|
12
|
+
'should return protection component': () =>
|
13
|
+
withProtectedView(ProtectedComponent, ProtectionComponent, () => false)(),
|
14
|
+
};
|
15
|
+
|
16
|
+
describe('withProtectedView', () =>
|
17
|
+
testSelectorsSnapshotWithFixtures(fixtures));
|
@@ -0,0 +1,60 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { LoadingState } from 'patternfly-react';
|
3
|
+
import PageLayout from 'foremanReact/routes/common/PageLayout/PageLayout';
|
4
|
+
import PropTypes from 'prop-types';
|
5
|
+
|
6
|
+
import NewTemplateSyncForm from './components/NewTemplateSyncForm';
|
7
|
+
import './NewTemplateSync.scss';
|
8
|
+
|
9
|
+
class NewTemplateSync extends React.Component {
|
10
|
+
componentDidMount() {
|
11
|
+
const {
|
12
|
+
apiUrls: { syncSettingsUrl },
|
13
|
+
getSyncSettings,
|
14
|
+
} = this.props;
|
15
|
+
getSyncSettings(syncSettingsUrl);
|
16
|
+
}
|
17
|
+
|
18
|
+
render() {
|
19
|
+
const {
|
20
|
+
apiUrls: { importUrl, exportUrl },
|
21
|
+
loadingSettings,
|
22
|
+
history,
|
23
|
+
validationData,
|
24
|
+
userPermissions,
|
25
|
+
} = this.props;
|
26
|
+
|
27
|
+
return (
|
28
|
+
<LoadingState loading={loadingSettings}>
|
29
|
+
<PageLayout
|
30
|
+
header={__('Import or Export Templates')}
|
31
|
+
searchable={false}
|
32
|
+
>
|
33
|
+
<NewTemplateSyncForm
|
34
|
+
validationData={validationData}
|
35
|
+
importUrl={importUrl}
|
36
|
+
exportUrl={exportUrl}
|
37
|
+
history={history}
|
38
|
+
userPermissions={userPermissions}
|
39
|
+
/>
|
40
|
+
</PageLayout>
|
41
|
+
</LoadingState>
|
42
|
+
);
|
43
|
+
}
|
44
|
+
}
|
45
|
+
|
46
|
+
NewTemplateSync.propTypes = {
|
47
|
+
getSyncSettings: PropTypes.func.isRequired,
|
48
|
+
apiUrls: PropTypes.object.isRequired,
|
49
|
+
userPermissions: PropTypes.object.isRequired,
|
50
|
+
history: PropTypes.object,
|
51
|
+
validationData: PropTypes.object,
|
52
|
+
loadingSettings: PropTypes.bool.isRequired,
|
53
|
+
};
|
54
|
+
|
55
|
+
NewTemplateSync.defaultProps = {
|
56
|
+
validationData: {},
|
57
|
+
history: {},
|
58
|
+
};
|
59
|
+
|
60
|
+
export default NewTemplateSync;
|
@@ -0,0 +1,19 @@
|
|
1
|
+
@import '~@theforeman/vendor/scss/variables';
|
2
|
+
|
3
|
+
.left-padded {
|
4
|
+
padding-left: 3%;
|
5
|
+
}
|
6
|
+
|
7
|
+
#foreman-templates {
|
8
|
+
.loading-state-pf.loading-state-pf-lg {
|
9
|
+
padding-top: 5%;
|
10
|
+
}
|
11
|
+
// No need to hide content, see #26122
|
12
|
+
#main > #content {
|
13
|
+
display: block;
|
14
|
+
}
|
15
|
+
|
16
|
+
.blank-slate-pf {
|
17
|
+
padding-top: 5%;
|
18
|
+
}
|
19
|
+
}
|
@@ -0,0 +1,39 @@
|
|
1
|
+
import api from 'foremanReact/API';
|
2
|
+
import { deepPropsToCamelCase } from 'foremanReact/common/helpers';
|
3
|
+
|
4
|
+
import {
|
5
|
+
SYNC_SETTINGS_REQUEST,
|
6
|
+
SYNC_SETTINGS_SUCCESS,
|
7
|
+
SYNC_SETTINGS_FAILURE,
|
8
|
+
SYNC_RESULT_PAGINATION_CHANGE,
|
9
|
+
} from '../../consts';
|
10
|
+
|
11
|
+
import { initialState } from '../TemplateSyncResult/TemplateSyncResultReducer';
|
12
|
+
|
13
|
+
export const getSyncSettings = url => async dispatch => {
|
14
|
+
dispatch({ type: SYNC_SETTINGS_REQUEST });
|
15
|
+
|
16
|
+
try {
|
17
|
+
const { data } = await api.get(url);
|
18
|
+
dispatch({
|
19
|
+
type: SYNC_RESULT_PAGINATION_CHANGE,
|
20
|
+
payload: { pagination: initialState.pagination },
|
21
|
+
});
|
22
|
+
return dispatch({
|
23
|
+
type: SYNC_SETTINGS_SUCCESS,
|
24
|
+
payload: {
|
25
|
+
...deepPropsToCamelCase(data),
|
26
|
+
},
|
27
|
+
});
|
28
|
+
} catch (error) {
|
29
|
+
return dispatch(errorHandler(SYNC_SETTINGS_FAILURE, error));
|
30
|
+
}
|
31
|
+
};
|
32
|
+
|
33
|
+
const errorHandler = (msg, err) => {
|
34
|
+
const error = {
|
35
|
+
errorMsg: 'Failed to fetch Settings for template sync from server.',
|
36
|
+
statusText: err.response.statusText,
|
37
|
+
};
|
38
|
+
return { type: msg, payload: { error } };
|
39
|
+
};
|
@@ -0,0 +1,34 @@
|
|
1
|
+
import Immutable from 'seamless-immutable';
|
2
|
+
|
3
|
+
import {
|
4
|
+
SYNC_SETTINGS_REQUEST,
|
5
|
+
SYNC_SETTINGS_SUCCESS,
|
6
|
+
SYNC_SETTINGS_FAILURE,
|
7
|
+
} from '../../consts';
|
8
|
+
|
9
|
+
export const initialState = Immutable({
|
10
|
+
loadingSettings: false,
|
11
|
+
importSettings: [],
|
12
|
+
exportSettings: [],
|
13
|
+
error: '',
|
14
|
+
});
|
15
|
+
|
16
|
+
const syncSettings = (state = initialState, action) => {
|
17
|
+
const { payload } = action;
|
18
|
+
switch (action.type) {
|
19
|
+
case SYNC_SETTINGS_REQUEST:
|
20
|
+
return state.set('loadingSettings', true);
|
21
|
+
case SYNC_SETTINGS_SUCCESS:
|
22
|
+
return state.merge({
|
23
|
+
loadingSettings: false,
|
24
|
+
importSettings: payload.results.import,
|
25
|
+
exportSettings: payload.results.export,
|
26
|
+
});
|
27
|
+
case SYNC_SETTINGS_FAILURE:
|
28
|
+
return state.merge({ error: payload.error, loadingSettings: false });
|
29
|
+
default:
|
30
|
+
return state;
|
31
|
+
}
|
32
|
+
};
|
33
|
+
|
34
|
+
export default syncSettings;
|
@@ -0,0 +1,7 @@
|
|
1
|
+
export const newSyncState = state => state.foremanTemplates.syncSettings;
|
2
|
+
|
3
|
+
export const selectImportSettings = state => newSyncState(state).importSettings;
|
4
|
+
export const selectExportSettings = state => newSyncState(state).exportSettings;
|
5
|
+
export const selectLoadingSettings = state =>
|
6
|
+
newSyncState(state).loadingSettings;
|
7
|
+
export const selectError = state => newSyncState(state).error;
|
@@ -0,0 +1,71 @@
|
|
1
|
+
import Immutable from 'seamless-immutable';
|
2
|
+
|
3
|
+
export const associateSetting = Immutable({
|
4
|
+
id: 45,
|
5
|
+
value: 'new',
|
6
|
+
settingsType: 'string',
|
7
|
+
name: 'associate',
|
8
|
+
selection: [
|
9
|
+
{ value: 'new', label: 'New' },
|
10
|
+
{ value: 'never', label: 'Never' },
|
11
|
+
{ value: 'always', label: 'Always' },
|
12
|
+
],
|
13
|
+
});
|
14
|
+
|
15
|
+
export const forceSetting = Immutable({
|
16
|
+
id: 46,
|
17
|
+
value: false,
|
18
|
+
settingsType: 'bool',
|
19
|
+
name: 'force',
|
20
|
+
});
|
21
|
+
|
22
|
+
export const importSettings = [associateSetting, forceSetting];
|
23
|
+
|
24
|
+
export const filterSetting = Immutable({
|
25
|
+
id: 47,
|
26
|
+
value: '',
|
27
|
+
settingsType: 'string',
|
28
|
+
name: 'filter',
|
29
|
+
});
|
30
|
+
|
31
|
+
export const negateSetting = Immutable({
|
32
|
+
id: 48,
|
33
|
+
value: false,
|
34
|
+
settingsType: 'bool',
|
35
|
+
name: 'negate',
|
36
|
+
});
|
37
|
+
|
38
|
+
export const repoSetting = Immutable({
|
39
|
+
id: 49,
|
40
|
+
value: 'https://github.com/theforeman/community-templates.git',
|
41
|
+
settingsType: 'string',
|
42
|
+
name: 'repo',
|
43
|
+
});
|
44
|
+
|
45
|
+
export const exportSettings = [filterSetting, negateSetting, repoSetting];
|
46
|
+
|
47
|
+
const registeredSettings = settings =>
|
48
|
+
settings.reduce((memo, item) => {
|
49
|
+
memo[item.name] = item;
|
50
|
+
return memo;
|
51
|
+
}, {});
|
52
|
+
|
53
|
+
export const registeredImportSettings = {
|
54
|
+
registeredFields: registeredSettings(importSettings),
|
55
|
+
};
|
56
|
+
export const registeredExportSettings = {
|
57
|
+
registeredFields: registeredSettings(exportSettings),
|
58
|
+
};
|
59
|
+
|
60
|
+
export const initialValues = {
|
61
|
+
initial: importSettings.concat(exportSettings).reduce((memo, item) => {
|
62
|
+
memo[item.name] = item.value;
|
63
|
+
return memo;
|
64
|
+
}, {}),
|
65
|
+
};
|
66
|
+
|
67
|
+
export const stateFactory = obj => ({
|
68
|
+
foremanTemplates: {
|
69
|
+
syncSettings: obj,
|
70
|
+
},
|
71
|
+
});
|
@@ -0,0 +1,31 @@
|
|
1
|
+
import { testComponentSnapshotsWithFixtures } from 'react-redux-test-utils';
|
2
|
+
|
3
|
+
import NewTemplateSync from '../NewTemplateSync';
|
4
|
+
|
5
|
+
jest.mock('foremanReact/routes/common/PageLayout/PageLayout');
|
6
|
+
|
7
|
+
const noop = () => {};
|
8
|
+
|
9
|
+
const commonFixture = {
|
10
|
+
apiUrls: {},
|
11
|
+
getSyncSettings: noop,
|
12
|
+
validationData: {},
|
13
|
+
userPermissions: {
|
14
|
+
import: true,
|
15
|
+
export: true,
|
16
|
+
},
|
17
|
+
};
|
18
|
+
|
19
|
+
const fixtures = {
|
20
|
+
'should render when loaded': {
|
21
|
+
loadingSettings: false,
|
22
|
+
...commonFixture,
|
23
|
+
},
|
24
|
+
'should render when loading': {
|
25
|
+
loadingSettings: true,
|
26
|
+
...commonFixture,
|
27
|
+
},
|
28
|
+
};
|
29
|
+
|
30
|
+
describe('NewTemplateSync', () =>
|
31
|
+
testComponentSnapshotsWithFixtures(NewTemplateSync, fixtures));
|
@@ -0,0 +1,55 @@
|
|
1
|
+
import { testReducerSnapshotWithFixtures } from 'react-redux-test-utils';
|
2
|
+
|
3
|
+
import reducer, { initialState } from '../NewTemplateSyncReducer';
|
4
|
+
|
5
|
+
import {
|
6
|
+
importSettings,
|
7
|
+
exportSettings,
|
8
|
+
} from '../__fixtures__/templateSyncSettings.fixtures';
|
9
|
+
import {
|
10
|
+
SYNC_SETTINGS_REQUEST,
|
11
|
+
SYNC_SETTINGS_SUCCESS,
|
12
|
+
SYNC_SETTINGS_FAILURE,
|
13
|
+
} from '../../../consts';
|
14
|
+
|
15
|
+
const successPayload = {
|
16
|
+
results: {
|
17
|
+
import: importSettings,
|
18
|
+
export: exportSettings,
|
19
|
+
},
|
20
|
+
};
|
21
|
+
|
22
|
+
const fixtures = {
|
23
|
+
'should return initial state': {
|
24
|
+
state: initialState,
|
25
|
+
action: {
|
26
|
+
type: undefined,
|
27
|
+
payload: {},
|
28
|
+
},
|
29
|
+
},
|
30
|
+
'should start loading on setting values request': {
|
31
|
+
state: initialState,
|
32
|
+
action: {
|
33
|
+
type: SYNC_SETTINGS_REQUEST,
|
34
|
+
},
|
35
|
+
},
|
36
|
+
'should stop loading on setting values success': {
|
37
|
+
state: initialState.set('loadingSettings', true),
|
38
|
+
action: {
|
39
|
+
type: SYNC_SETTINGS_SUCCESS,
|
40
|
+
payload: successPayload,
|
41
|
+
},
|
42
|
+
'should stop loading on setting values error': {
|
43
|
+
state: initialState.set('loadingSettings', true),
|
44
|
+
action: {
|
45
|
+
type: SYNC_SETTINGS_FAILURE,
|
46
|
+
payload: {
|
47
|
+
error: 'Failed to fetch setting values',
|
48
|
+
},
|
49
|
+
},
|
50
|
+
},
|
51
|
+
},
|
52
|
+
};
|
53
|
+
|
54
|
+
describe('NewTemplateSyncReducer', () =>
|
55
|
+
testReducerSnapshotWithFixtures(reducer, fixtures));
|
@@ -0,0 +1,28 @@
|
|
1
|
+
import { testSelectorsSnapshotWithFixtures } from 'react-redux-test-utils';
|
2
|
+
|
3
|
+
import {
|
4
|
+
importSettings,
|
5
|
+
exportSettings,
|
6
|
+
stateFactory,
|
7
|
+
} from '../__fixtures__/templateSyncSettings.fixtures';
|
8
|
+
|
9
|
+
import {
|
10
|
+
selectImportSettings,
|
11
|
+
selectExportSettings,
|
12
|
+
selectLoadingSettings,
|
13
|
+
selectError,
|
14
|
+
} from '../NewTemplateSyncSelectors';
|
15
|
+
|
16
|
+
const fixtures = {
|
17
|
+
'should return import settings': () =>
|
18
|
+
selectImportSettings(stateFactory({ importSettings })),
|
19
|
+
'should return export settings': () =>
|
20
|
+
selectExportSettings(stateFactory({ exportSettings })),
|
21
|
+
'should return loading settings': () =>
|
22
|
+
selectLoadingSettings(stateFactory({ loadingSettings: true })),
|
23
|
+
'should return loading error': () =>
|
24
|
+
selectError(stateFactory({ error: 'Error' })),
|
25
|
+
};
|
26
|
+
|
27
|
+
describe('NewTemplateSyncSelectors', () =>
|
28
|
+
testSelectorsSnapshotWithFixtures(fixtures));
|
@@ -0,0 +1,53 @@
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
2
|
+
|
3
|
+
exports[`NewTemplateSync should render when loaded 1`] = `
|
4
|
+
<LoadingState
|
5
|
+
additionalClasses=""
|
6
|
+
loading={false}
|
7
|
+
loadingText="Loading"
|
8
|
+
size="lg"
|
9
|
+
timeout={300}
|
10
|
+
>
|
11
|
+
<PageLayout
|
12
|
+
header="Import or Export Templates"
|
13
|
+
searchable={false}
|
14
|
+
>
|
15
|
+
<Connect(ReduxForm)
|
16
|
+
history={Object {}}
|
17
|
+
userPermissions={
|
18
|
+
Object {
|
19
|
+
"export": true,
|
20
|
+
"import": true,
|
21
|
+
}
|
22
|
+
}
|
23
|
+
validationData={Object {}}
|
24
|
+
/>
|
25
|
+
</PageLayout>
|
26
|
+
</LoadingState>
|
27
|
+
`;
|
28
|
+
|
29
|
+
exports[`NewTemplateSync should render when loading 1`] = `
|
30
|
+
<LoadingState
|
31
|
+
additionalClasses=""
|
32
|
+
loading={true}
|
33
|
+
loadingText="Loading"
|
34
|
+
size="lg"
|
35
|
+
timeout={300}
|
36
|
+
>
|
37
|
+
<PageLayout
|
38
|
+
header="Import or Export Templates"
|
39
|
+
searchable={false}
|
40
|
+
>
|
41
|
+
<Connect(ReduxForm)
|
42
|
+
history={Object {}}
|
43
|
+
userPermissions={
|
44
|
+
Object {
|
45
|
+
"export": true,
|
46
|
+
"import": true,
|
47
|
+
}
|
48
|
+
}
|
49
|
+
validationData={Object {}}
|
50
|
+
/>
|
51
|
+
</PageLayout>
|
52
|
+
</LoadingState>
|
53
|
+
`;
|