Registered remaining short URLs components in DI container

This commit is contained in:
Alejandro Celaya 2018-12-17 23:11:55 +01:00
parent bec755b121
commit bab1e57ab1
9 changed files with 56 additions and 69 deletions

View file

@ -6,11 +6,10 @@ import FontAwesomeIcon from '@fortawesome/react-fontawesome';
import classnames from 'classnames'; import classnames from 'classnames';
import * as PropTypes from 'prop-types'; import * as PropTypes from 'prop-types';
import ShortUrlsVisits from '../visits/ShortUrlVisits'; import ShortUrlsVisits from '../visits/ShortUrlVisits';
import CreateShortUrl from '../short-urls/CreateShortUrl';
import './MenuLayout.scss'; import './MenuLayout.scss';
import { serverType } from '../servers/prop-types'; import { serverType } from '../servers/prop-types';
const MenuLayout = (TagsList, ShortUrls, AsideMenu) => class MenuLayout extends React.Component { const MenuLayout = (TagsList, ShortUrls, AsideMenu, CreateShortUrl) => class MenuLayout extends React.Component {
static propTypes = { static propTypes = {
match: PropTypes.object, match: PropTypes.object,
selectServer: PropTypes.func, selectServer: PropTypes.func,

View file

@ -15,7 +15,7 @@ import { createServer, createServers, deleteServer, listServers } from '../serve
import CreateServer from '../servers/CreateServer'; import CreateServer from '../servers/CreateServer';
import ServersDropdown from '../servers/ServersDropdown'; import ServersDropdown from '../servers/ServersDropdown';
import TagsList from '../tags/TagsList'; import TagsList from '../tags/TagsList';
import { filterTags, forceListTags } from '../tags/reducers/tagsList'; import { filterTags, forceListTags, listTags } from '../tags/reducers/tagsList';
import ShortUrls from '../short-urls/ShortUrls'; import ShortUrls from '../short-urls/ShortUrls';
import SearchBar from '../short-urls/SearchBar'; import SearchBar from '../short-urls/SearchBar';
import { listShortUrls } from '../short-urls/reducers/shortUrlsList'; import { listShortUrls } from '../short-urls/reducers/shortUrlsList';
@ -34,6 +34,13 @@ import ImportServersBtn from '../servers/helpers/ImportServersBtn';
import { ServersImporter } from '../servers/services/ServersImporter'; import { ServersImporter } from '../servers/services/ServersImporter';
import { ServersExporter } from '../servers/services/ServersExporter'; import { ServersExporter } from '../servers/services/ServersExporter';
import { ServersService } from '../servers/services/ServersService'; import { ServersService } from '../servers/services/ServersService';
import CreateShortUrl from '../short-urls/CreateShortUrl';
import { createShortUrl, resetCreateShortUrl } from '../short-urls/reducers/shortUrlCreation';
import TagsSelector from '../tags/helpers/TagsSelector';
import DeleteShortUrlModal from '../short-urls/helpers/DeleteShortUrlModal';
import { deleteShortUrl, resetDeleteShortUrl, shortUrlDeleted } from '../short-urls/reducers/shortUrlDeletion';
import EditTagsModal from '../short-urls/helpers/EditTagsModal';
import { editShortUrlTags, resetShortUrlsTags, shortUrlTagsEdited } from '../short-urls/reducers/shortUrlTags';
const bottle = new Bottle(); const bottle = new Bottle();
@ -46,7 +53,7 @@ bottle.decorator('MainHeader', withRouter);
bottle.serviceFactory('Home', () => Home); bottle.serviceFactory('Home', () => Home);
bottle.decorator('Home', connect(pick([ 'servers' ]), { resetSelectedServer })); bottle.decorator('Home', connect(pick([ 'servers' ]), { resetSelectedServer }));
bottle.serviceFactory('MenuLayout', MenuLayout, 'TagsList', 'ShortUrls', 'AsideMenu'); bottle.serviceFactory('MenuLayout', MenuLayout, 'TagsList', 'ShortUrls', 'AsideMenu', 'CreateShortUrl');
bottle.decorator( bottle.decorator(
'MenuLayout', 'MenuLayout',
compose( compose(
@ -88,7 +95,7 @@ bottle.service('ColorGenerator', ColorGenerator, 'Storage');
bottle.serviceFactory('ShortUrlsRow', ShortUrlsRow, 'Tag', 'ShortUrlsRowMenu'); bottle.serviceFactory('ShortUrlsRow', ShortUrlsRow, 'Tag', 'ShortUrlsRowMenu');
bottle.serviceFactory('ShortUrlsRowMenu', () => ShortUrlsRowMenu); bottle.serviceFactory('ShortUrlsRowMenu', ShortUrlsRowMenu, 'DeleteShortUrlModal', 'EditTagsModal');
bottle.constant('axios', axios); bottle.constant('axios', axios);
bottle.service('ShlinkApiClient', ShlinkApiClient, 'axios'); bottle.service('ShlinkApiClient', ShlinkApiClient, 'axios');
@ -108,4 +115,24 @@ bottle.service('ServersImporter', ServersImporter, 'csvjson');
bottle.service('ServersService', ServersService, 'Storage'); bottle.service('ServersService', ServersService, 'Storage');
bottle.service('ServersExporter', ServersExporter, 'ServersService', 'window', 'csvjson'); bottle.service('ServersExporter', ServersExporter, 'ServersService', 'window', 'csvjson');
bottle.serviceFactory('CreateShortUrl', CreateShortUrl, 'TagsSelector');
bottle.decorator('CreateShortUrl', connect(pick([ 'shortUrlCreationResult' ]), {
createShortUrl,
resetCreateShortUrl,
}));
bottle.serviceFactory('TagsSelector', TagsSelector, 'ColorGenerator');
bottle.decorator('TagsSelector', connect(pick([ 'tagsList' ]), { listTags }));
bottle.serviceFactory('DeleteShortUrlModal', () => DeleteShortUrlModal);
bottle.decorator('DeleteShortUrlModal', connect(
pick([ 'shortUrlDeletion' ]),
{ deleteShortUrl, resetDeleteShortUrl, shortUrlDeleted }
));
bottle.serviceFactory('EditTagsModal', EditTagsModal, 'TagsSelector');
bottle.decorator('EditTagsModal', connect(
pick([ 'shortUrlTags' ]),
{ editShortUrlTags, resetShortUrlsTags, shortUrlTagsEdited }
));
export default bottle.container; export default bottle.container;

View file

@ -1,20 +1,18 @@
import downIcon from '@fortawesome/fontawesome-free-solid/faAngleDoubleDown'; import downIcon from '@fortawesome/fontawesome-free-solid/faAngleDoubleDown';
import upIcon from '@fortawesome/fontawesome-free-solid/faAngleDoubleUp'; import upIcon from '@fortawesome/fontawesome-free-solid/faAngleDoubleUp';
import FontAwesomeIcon from '@fortawesome/react-fontawesome'; import FontAwesomeIcon from '@fortawesome/react-fontawesome';
import { assoc, dissoc, isNil, pick, pipe, replace, trim } from 'ramda'; import { assoc, dissoc, isNil, pipe, replace, trim } from 'ramda';
import React from 'react'; import React from 'react';
import { connect } from 'react-redux';
import { Collapse } from 'reactstrap'; import { Collapse } from 'reactstrap';
import * as PropTypes from 'prop-types'; import * as PropTypes from 'prop-types';
import DateInput from '../utils/DateInput'; import DateInput from '../utils/DateInput';
import TagsSelector from '../tags/helpers/TagsSelector';
import CreateShortUrlResult from './helpers/CreateShortUrlResult'; import CreateShortUrlResult from './helpers/CreateShortUrlResult';
import { createShortUrl, createShortUrlResultType, resetCreateShortUrl } from './reducers/shortUrlCreation'; import { createShortUrlResultType } from './reducers/shortUrlCreation';
const normalizeTag = pipe(trim, replace(/ /g, '-')); const normalizeTag = pipe(trim, replace(/ /g, '-'));
const formatDate = (date) => isNil(date) ? date : date.format(); const formatDate = (date) => isNil(date) ? date : date.format();
export class CreateShortUrlComponent extends React.Component { const CreateShortUrl = (TagsSelector) => class CreateShortUrl extends React.Component {
static propTypes = { static propTypes = {
createShortUrl: PropTypes.func, createShortUrl: PropTypes.func,
shortUrlCreationResult: createShortUrlResultType, shortUrlCreationResult: createShortUrlResultType,
@ -122,11 +120,6 @@ export class CreateShortUrlComponent extends React.Component {
</div> </div>
); );
} }
} };
const CreateShortUrl = connect(pick([ 'shortUrlCreationResult' ]), {
createShortUrl,
resetCreateShortUrl,
})(CreateShortUrlComponent);
export default CreateShortUrl; export default CreateShortUrl;

View file

@ -1,18 +1,11 @@
import React, { Component } from 'react'; import React from 'react';
import { connect } from 'react-redux';
import { Modal, ModalBody, ModalFooter, ModalHeader } from 'reactstrap'; import { Modal, ModalBody, ModalFooter, ModalHeader } from 'reactstrap';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { pick, identity } from 'ramda'; import { identity } from 'ramda';
import { shortUrlType } from '../reducers/shortUrlsList'; import { shortUrlType } from '../reducers/shortUrlsList';
import { import { shortUrlDeletionType } from '../reducers/shortUrlDeletion';
deleteShortUrl,
resetDeleteShortUrl,
shortUrlDeleted,
shortUrlDeletionType,
} from '../reducers/shortUrlDeletion';
import './QrCodeModal.scss';
export class DeleteShortUrlModalComponent extends Component { export default class DeleteShortUrlModal extends React.Component {
static propTypes = { static propTypes = {
shortUrl: shortUrlType, shortUrl: shortUrlType,
toggle: PropTypes.func, toggle: PropTypes.func,
@ -94,10 +87,3 @@ export class DeleteShortUrlModalComponent extends Component {
); );
} }
} }
const DeleteShortUrlModal = connect(
pick([ 'shortUrlDeletion' ]),
{ deleteShortUrl, resetDeleteShortUrl, shortUrlDeleted }
)(DeleteShortUrlModalComponent);
export default DeleteShortUrlModal;

View file

@ -1,19 +1,11 @@
import React from 'react'; import React from 'react';
import { connect } from 'react-redux';
import { Modal, ModalBody, ModalFooter, ModalHeader } from 'reactstrap'; import { Modal, ModalBody, ModalFooter, ModalHeader } from 'reactstrap';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { pick } from 'ramda'; import { shortUrlTagsType } from '../reducers/shortUrlTags';
import TagsSelector from '../../tags/helpers/TagsSelector';
import {
editShortUrlTags,
resetShortUrlsTags,
shortUrlTagsType,
shortUrlTagsEdited,
} from '../reducers/shortUrlTags';
import ExternalLink from '../../utils/ExternalLink'; import ExternalLink from '../../utils/ExternalLink';
import { shortUrlType } from '../reducers/shortUrlsList'; import { shortUrlType } from '../reducers/shortUrlsList';
export class EditTagsModalComponent extends React.Component { const EditTagsModal = (TagsSelector) => class EditTagsModal extends React.Component {
static propTypes = { static propTypes = {
isOpen: PropTypes.bool.isRequired, isOpen: PropTypes.bool.isRequired,
toggle: PropTypes.func.isRequired, toggle: PropTypes.func.isRequired,
@ -88,11 +80,6 @@ export class EditTagsModalComponent extends React.Component {
</Modal> </Modal>
); );
} }
} };
const EditTagsModal = connect(
pick([ 'shortUrlTags' ]),
{ editShortUrlTags, resetShortUrlsTags, shortUrlTagsEdited }
)(EditTagsModalComponent);
export default EditTagsModal; export default EditTagsModal;

View file

@ -15,11 +15,9 @@ import { serverType } from '../../servers/prop-types';
import { shortUrlType } from '../reducers/shortUrlsList'; import { shortUrlType } from '../reducers/shortUrlsList';
import PreviewModal from './PreviewModal'; import PreviewModal from './PreviewModal';
import QrCodeModal from './QrCodeModal'; import QrCodeModal from './QrCodeModal';
import EditTagsModal from './EditTagsModal';
import DeleteShortUrlModal from './DeleteShortUrlModal';
import './ShortUrlsRowMenu.scss'; import './ShortUrlsRowMenu.scss';
export default class ShortUrlsRowMenu extends React.Component { const ShortUrlsRowMenu = (DeleteShortUrlModal, EditTagsModal) => class ShortUrlsRowMenu extends React.Component {
static propTypes = { static propTypes = {
completeShortUrl: PropTypes.string, completeShortUrl: PropTypes.string,
onCopyToClipboard: PropTypes.func, onCopyToClipboard: PropTypes.func,
@ -105,4 +103,6 @@ export default class ShortUrlsRowMenu extends React.Component {
</ButtonDropdown> </ButtonDropdown>
); );
} }
} };
export default ShortUrlsRowMenu;

View file

@ -1,26 +1,21 @@
import React from 'react'; import React from 'react';
import { connect } from 'react-redux';
import TagsInput from 'react-tagsinput'; import TagsInput from 'react-tagsinput';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import Autosuggest from 'react-autosuggest'; import Autosuggest from 'react-autosuggest';
import { pick, identity } from 'ramda'; import { identity } from 'ramda';
import { listTags } from '../reducers/tagsList';
import colorGenerator, { colorGeneratorType } from '../../utils/ColorGenerator';
import './TagsSelector.scss';
import TagBullet from './TagBullet'; import TagBullet from './TagBullet';
import './TagsSelector.scss';
export class TagsSelectorComponent extends React.Component { const TagsSelector = (colorGenerator) => class TagsSelector extends React.Component {
static propTypes = { static propTypes = {
tags: PropTypes.arrayOf(PropTypes.string).isRequired, tags: PropTypes.arrayOf(PropTypes.string).isRequired,
onChange: PropTypes.func.isRequired, onChange: PropTypes.func.isRequired,
placeholder: PropTypes.string, placeholder: PropTypes.string,
colorGenerator: colorGeneratorType,
tagsList: PropTypes.shape({ tagsList: PropTypes.shape({
tags: PropTypes.arrayOf(PropTypes.string), tags: PropTypes.arrayOf(PropTypes.string),
}), }),
}; };
static defaultProps = { static defaultProps = {
colorGenerator,
placeholder: 'Add tags to the URL', placeholder: 'Add tags to the URL',
}; };
@ -31,7 +26,7 @@ export class TagsSelectorComponent extends React.Component {
} }
render() { render() {
const { tags, onChange, placeholder, colorGenerator, tagsList } = this.props; const { tags, onChange, placeholder, tagsList } = this.props;
const renderTag = ({ tag, key, disabled, onRemove, classNameRemove, getTagDisplayValue, ...other }) => ( const renderTag = ({ tag, key, disabled, onRemove, classNameRemove, getTagDisplayValue, ...other }) => (
<span key={key} style={{ backgroundColor: colorGenerator.getColorForKey(tag) }} {...other}> <span key={key} style={{ backgroundColor: colorGenerator.getColorForKey(tag) }} {...other}>
{getTagDisplayValue(tag)} {getTagDisplayValue(tag)}
@ -86,8 +81,6 @@ export class TagsSelectorComponent extends React.Component {
/> />
); );
} }
} };
const TagsSelector = connect(pick([ 'tagsList' ]), { listTags })(TagsSelectorComponent);
export default TagsSelector; export default TagsSelector;

View file

@ -3,18 +3,20 @@ import { shallow } from 'enzyme';
import moment from 'moment'; import moment from 'moment';
import * as sinon from 'sinon'; import * as sinon from 'sinon';
import { identity } from 'ramda'; import { identity } from 'ramda';
import { CreateShortUrlComponent as CreateShortUrl } from '../../src/short-urls/CreateShortUrl'; import createShortUrlsCreator from '../../src/short-urls/CreateShortUrl';
import TagsSelector from '../../src/tags/helpers/TagsSelector';
import DateInput from '../../src/utils/DateInput'; import DateInput from '../../src/utils/DateInput';
describe('<CreateShortUrl />', () => { describe('<CreateShortUrl />', () => {
let wrapper; let wrapper;
const TagsSelector = () => '';
const shortUrlCreationResult = { const shortUrlCreationResult = {
loading: false, loading: false,
}; };
const createShortUrl = sinon.spy(); const createShortUrl = sinon.spy();
beforeEach(() => { beforeEach(() => {
const CreateShortUrl = createShortUrlsCreator(TagsSelector);
wrapper = shallow( wrapper = shallow(
<CreateShortUrl shortUrlCreationResult={shortUrlCreationResult} createShortUrl={createShortUrl} /> <CreateShortUrl shortUrlCreationResult={shortUrlCreationResult} createShortUrl={createShortUrl} />
); );

View file

@ -2,7 +2,7 @@ import React from 'react';
import { shallow } from 'enzyme'; import { shallow } from 'enzyme';
import { identity } from 'ramda'; import { identity } from 'ramda';
import * as sinon from 'sinon'; import * as sinon from 'sinon';
import { DeleteShortUrlModalComponent as DeleteShortUrlModal } from '../../../src/short-urls/helpers/DeleteShortUrlModal'; import DeleteShortUrlModal from '../../../src/short-urls/helpers/DeleteShortUrlModal';
describe('<DeleteShortUrlModal />', () => { describe('<DeleteShortUrlModal />', () => {
let wrapper; let wrapper;