Skip to content

Commit

Permalink
Merge pull request #73 from Inist-CNRS/refactoring
Browse files Browse the repository at this point in the history
[WIP] Refactoring
  • Loading branch information
ThieryMichel authored Feb 20, 2017
2 parents 729cda2 + fe1f006 commit 08910ba
Show file tree
Hide file tree
Showing 143 changed files with 1,134 additions and 906 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@
"request": "2.79.0",
"reselect": "2.5.4",
"stream-buffers": "3.0.1",
"url-polyfill": "webcomponents/URL",
"url-api-polyfill": "1.1.0",
"whatwg-fetch": "2.0.2",
"winston": "2.3.0"
},
Expand Down Expand Up @@ -108,8 +108,8 @@
"selenium-webdriver": "3.0.1",
"url-loader": "0.5.7",
"webpack": "2.2.0",
"webpack-dev-server": "2.2.0",
"webpack-dev-middleware": "1.10.0",
"webpack-dev-server": "2.2.0",
"webpack-hot-middleware": "2.17.0"
},
"pre-commit": [
Expand Down
5 changes: 2 additions & 3 deletions src/app/e2e/admin/publication.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ describe('Admin', () => {

before(async () => {
await clear();
await loginAsJulia();
await driver.get('http://localhost:3010/#/admin');
await loginAsJulia('/admin');
});

describe('Uploading', () => {
Expand Down Expand Up @@ -228,8 +227,8 @@ describe('Admin', () => {
});

after(async () => {
await clear();
await driver.executeScript('localStorage.clear();');
await clear();
});
});
});
3 changes: 1 addition & 2 deletions src/app/e2e/admin/resources.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ describe('Admin', () => {
before(async () => {
await clear(); // Had to ensure clear state for unknown reason
await loadFixtures(fixtures);
await loginAsJulia();
await driver.get('http://localhost:3010/#/admin');
await loginAsJulia('/admin');
});

it('should display the removed resources', async () => {
Expand Down
2 changes: 1 addition & 1 deletion src/app/e2e/home_published_julia.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ describe('Home page with published data when logged as Julia', function homePubl
before(async () => {
await clear();
await loadFixtures(fixtures);
await loginAsJulia();
await loginAsJulia('/');
});

it('should display the list with an edit button', async () => {
Expand Down
16 changes: 5 additions & 11 deletions src/app/e2e/loginAsJulia.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,14 @@
import { until, By } from 'selenium-webdriver';

import driver from '../../common/tests/chromeDriver';
import { elementIsClicked, inputElementIsFocusable } from '../../common/tests/conditions';
import { inputElementIsFocusable } from '../../common/tests/conditions';

const DEFAULT_WAIT_TIMEOUT = 9000; // A bit less than mocha's timeout to get explicit errors from selenium

export default async () => {
await driver.get('http://localhost:3010/');
export default async (nextpathname) => {
await driver.get(`http://localhost:3010/?nextpathname=${nextpathname}#/login`);

const button = await driver.findElement(By.css('.appbar button'));
await driver.wait(elementIsClicked(button), DEFAULT_WAIT_TIMEOUT);

const buttonSignIn = await driver.findElement(By.css('.btn-sign-in'));
await driver.wait(elementIsClicked(buttonSignIn), DEFAULT_WAIT_TIMEOUT);

const form = await driver.findElement(By.css('.dialog-login form'));
const form = await driver.findElement(By.css('form'));
const username = await driver.findElement(By.css('input[name=username]'));
const password = await driver.findElement(By.css('input[name=password]'));
await driver.wait(inputElementIsFocusable(username, true), DEFAULT_WAIT_TIMEOUT);
Expand All @@ -23,5 +17,5 @@ export default async () => {
await username.sendKeys('user');
await password.sendKeys('secret');
await form.submit();
await driver.wait(until.stalenessOf(form), DEFAULT_WAIT_TIMEOUT);
await driver.wait(until.urlMatches(new RegExp(nextpathname)));
};
15 changes: 6 additions & 9 deletions src/app/js/admin/Admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,18 @@ import { polyglot as polyglotPropTypes } from '../propTypes';

import {
loadParsingResult as loadParsingResultAction,
hasUploadedFile as selectHasUploadedFile,
isParsingLoading,
} from './parsing';
import {
loadPublication as loadPublicationAction,
hasPublishedDataset as selectHasPublishedDataset,
} from '../publication';
} from './publication';
import { fromParsing, fromPublication, fromUpload } from './selectors';
import ParsingResult from './parsing/ParsingResult';
import PublicationPreview from './publicationPreview/PublicationPreview';
import Publish from './publish/Publish';
import Published from '../publication/Published';
import Published from './publish/Published';
import RemovedResourceList from './removedResources/RemovedResourceList';
import Upload from './upload/Upload';
import Loading from '../lib/Loading';
import { isUploadPending } from './upload';

export class AdminComponent extends Component {
static propTypes = {
Expand Down Expand Up @@ -78,9 +75,9 @@ export class AdminComponent extends Component {
}

const mapStateToProps = state => ({
loadingParsingResult: isParsingLoading(state) || isUploadPending(state),
hasUploadedFile: selectHasUploadedFile(state),
hasPublishedDataset: selectHasPublishedDataset(state),
loadingParsingResult: fromParsing.isParsingLoading(state) || fromUpload.isUploadPending(state),
hasUploadedFile: fromParsing.hasUploadedFile(state),
hasPublishedDataset: fromPublication.hasPublishedDataset(state),
});

const mapDispatchToProps = ({
Expand Down
6 changes: 2 additions & 4 deletions src/app/js/admin/fields/FieldForm.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { PropTypes } from 'react';
import React from 'react';
import compose from 'recompose/compose';
import { connect } from 'react-redux';
import translate from 'redux-polyglot/translate';
Expand All @@ -14,8 +14,7 @@ import {
saveField,
} from './';

import { fromFields } from '../../selectors';

import { fromFields } from '../selectors';
import Format from '../../formats/FormatEdition';
import Alert from '../../lib/Alert';
import TransformerList from './TransformerList';
Expand Down Expand Up @@ -87,7 +86,6 @@ FieldFormComponent.defaultProps = {
FieldFormComponent.propTypes = {
...reduxFormPropTypes,
p: polyglotPropTypes.isRequired,
getSchemeSearchRequest: PropTypes.func.isRequired,
};

const mapStateToProps = state => ({
Expand Down
9 changes: 6 additions & 3 deletions src/app/js/admin/fields/TransformerArgList.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
/* eslint react/no-array-index-key: off */
import React from 'react';
import React, { PropTypes } from 'react';
import pure from 'recompose/pure';
import { propTypes as reduxFormPropTypes } from 'redux-form';

import TransformerArgListItem from './TransformerArgListItem';

Expand All @@ -18,6 +17,10 @@ const TransformerArgList = ({ fields }) => (
</div>
);

TransformerArgList.propTypes = reduxFormPropTypes;
TransformerArgList.propTypes = {
fields: PropTypes.shape({
map: PropTypes.func.isRequired,
}).isRequired,
};

export default pure(TransformerArgList);
11 changes: 6 additions & 5 deletions src/app/js/admin/fields/TransformerArgListItem.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import React from 'react';
import React, { PropTypes } from 'react';
import pure from 'recompose/pure';
import { Field, propTypes as reduxFormPropTypes } from 'redux-form';
import { Field } from 'redux-form';

import { polyglot as polyglotPropTypes } from '../../propTypes';
import FormTextField from '../../lib/FormTextField';

const TransformerArgListItem = ({ fieldName, transformerArg }) => (
Expand All @@ -16,8 +15,10 @@ const TransformerArgListItem = ({ fieldName, transformerArg }) => (
);

TransformerArgListItem.propTypes = {
...reduxFormPropTypes,
p: polyglotPropTypes.isRequired,
fieldName: PropTypes.string.isRequired,
transformerArg: PropTypes.shape({
name: PropTypes.string.isRequired,
}).isRequired,
};

export default pure(TransformerArgListItem);
18 changes: 11 additions & 7 deletions src/app/js/admin/fields/TransformerList.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
/* eslint react/no-array-index-key: off */

import React from 'react';
import React, { PropTypes } from 'react';
import compose from 'recompose/compose';
import translate from 'redux-polyglot/translate';
import pure from 'recompose/pure';

import FlatButton from 'material-ui/FlatButton';
import { propTypes as reduxFormPropTypes } from 'redux-form';

import { polyglot as polyglotPropTypes } from '../../propTypes';
import TransformerListItem from './TransformerListItem';
Expand All @@ -17,7 +13,7 @@ const TransformerList = ({ fields, meta: { touched, error }, p: polyglot }) => (

{fields.map((fieldName, index) => (
<TransformerListItem
key={index}
key={fieldName}
fieldName={fieldName}
onRemove={() => fields.remove(index)}
operation={fields.get(index).operation}
Expand All @@ -32,7 +28,15 @@ const TransformerList = ({ fields, meta: { touched, error }, p: polyglot }) => (
);

TransformerList.propTypes = {
...reduxFormPropTypes,
fields: PropTypes.shape({
map: PropTypes.func.isRequired,
get: PropTypes.func.isRequired,
remove: PropTypes.func.isRequired,
}).isRequired,
meta: PropTypes.shape({
touched: PropTypes.bool,
error: PropTypes.string,
}).isRequired,
p: polyglotPropTypes.isRequired,
};

Expand Down
17 changes: 10 additions & 7 deletions src/app/js/admin/fields/TransformerListItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import translate from 'redux-polyglot/translate';
import IconButton from 'material-ui/IconButton';
import MenuItem from 'material-ui/MenuItem';
import ActionDeleteIcon from 'material-ui/svg-icons/action/delete';
import { Field, FieldArray, propTypes as reduxFormPropTypes } from 'redux-form';
import { Field, FieldArray } from 'redux-form';

import { polyglot as polyglotPropTypes } from '../../propTypes';
import { getTransformers, getTransformerArgs } from './';
import { fromFields } from '../selectors';
import FormSelectField from '../../lib/FormSelectField';
import TransformerArgList from './TransformerArgList';

Expand All @@ -34,7 +34,9 @@ const TransformerListItem = ({ availableTransformers, fieldName, onRemove, p: po
component={FormSelectField}
label={polyglot.t('select_an_operation')}
>
{availableTransformers.map(t => <MenuItem className={t.name} value={t.name} primaryText={t.name} />)}
{availableTransformers.map(
t => <MenuItem key={t.name} className={t.name} value={t.name} primaryText={t.name} />,
)}
</Field>
<FieldArray name={`${fieldName}.args`} component={TransformerArgList} />
</div>
Expand All @@ -43,15 +45,16 @@ const TransformerListItem = ({ availableTransformers, fieldName, onRemove, p: po
TransformerListItem.propTypes = {
availableTransformers: PropTypes.arrayOf(PropTypes.shape({
name: PropTypes.string.isRequired,
type: PropTypes.string.isRequired,
args: PropTypes.arrayOf(PropTypes.any).isRequired,
})).isRequired,
...reduxFormPropTypes,
fieldName: PropTypes.string.isRequired,
onRemove: PropTypes.func.isRequired,
p: polyglotPropTypes.isRequired,
};

const mapStateToProps = (state, ownProps) => ({
availableTransformers: getTransformers(state),
transformerArgs: getTransformerArgs(state, ownProps.operation),
availableTransformers: fromFields.getTransformers(state),
transformerArgs: fromFields.getTransformerArgs(state, ownProps.operation),
});

export default compose(
Expand Down
51 changes: 33 additions & 18 deletions src/app/js/admin/fields/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { createAction, handleActions } from 'redux-actions';
import { createSelector } from 'reselect';

import { getTransformersMetas, getTransformerMetas } from '../../../../common/transformers';
import { COVER_COLLECTION } from '../../../../common/cover';

export const FIELD_FORM_NAME = 'field';

Expand All @@ -17,6 +18,7 @@ export const REMOVE_FIELD = 'REMOVE_FIELD';
export const REMOVE_FIELD_ERROR = 'REMOVE_FIELD_ERROR';
export const REMOVE_FIELD_SUCCESS = 'REMOVE_FIELD_SUCCESS';
export const REFRESH_FIELD = 'REFRESH_FIELD';
export const SET_VALIDATION = 'SET_VALIDATION';
export const UPDATE_FIELD_ERROR = 'UPDATE_FIELD_ERROR';
export const UPDATE_FIELD_SUCCESS = 'UPDATE_FIELD_SUCCESS';

Expand All @@ -31,11 +33,13 @@ export const removeField = createAction(REMOVE_FIELD);
export const removeFieldError = createAction(REMOVE_FIELD_ERROR);
export const removeFieldSuccess = createAction(REMOVE_FIELD_SUCCESS);
export const refreshField = createAction(REFRESH_FIELD);
export const setValidation = createAction(SET_VALIDATION);
export const updateFieldError = createAction(UPDATE_FIELD_ERROR);
export const updateFieldSuccess = createAction(UPDATE_FIELD_SUCCESS);

export const defaultState = {
byId: {},
allValid: true,
list: [],
editedFieldId: null,
};
Expand Down Expand Up @@ -75,6 +79,10 @@ export default handleActions({
[payload._id]: payload,
},
}),
SET_VALIDATION: (state, { payload }) => ({
...state,
...payload,
}),
}, defaultState);

const getFields = ({ byId, list }) => list.map(id => byId[id]);
Expand All @@ -83,34 +91,41 @@ const getNbFields = ({ list }) => list.length;

const getEditedField = state => state.byId[state.editedFieldId];

export const getCollectionFields = createSelector(
getFields,
fields => fields.filter(f => f.cover === COVER_COLLECTION),
);

export const hasPublicationFields = ({ list }) => list.length > 0;

export const getTransformers = () => getTransformersMetas();

export const getTransformerArgs = (state, operation) => getTransformerMetas(operation);

export const getFieldFormData = state => state.form.field.values;

export const getSchemeSearchRequest = (state, query) => ({
url: `http://lov.okfn.org/dataset/lov/api/v2/term/autocomplete?q=${query}`,
});
const getValidationFields = state => state.fields;

export const getSchemeMenuItemsDataFromResponse = (state, response) => (
response && response.results
? response.results.map(r => ({ label: r.localName[0], uri: r.uri[0] }))
: []
export const getInvalidFields = createSelector(
getFields,
getValidationFields,
(fields = [], validationFields = []) => validationFields
.filter(({ isValid }) => !isValid)
.map(field => ({
...field,
index: fields.findIndex(f => f.name === field.name),
})),
);

// @TODO use future version
const multiCreateSelector = (baseSelector, selectors) =>
Object.keys(selectors).reduce((acc, key) => ({
...acc,
[key]: createSelector(baseSelector, (_, props) => props, selectors[key]),
}), {});
export const areAllFieldsValid = state => state.allValid;

export const fromFields = {
export const selectors = {
areAllFieldsValid,
getFields,
getNbFields,
getCollectionFields,
getEditedField,
getNbFields,
hasPublicationFields,
getTransformers,
getTransformerArgs,
};

// @TODO move in selectors file
export const fromGlobale = multiCreateSelector(state => state.fields, fromFields);
Loading

0 comments on commit 08910ba

Please sign in to comment.