mirror of
https://github.com/shlinkio/shlink-web-client.git
synced 2025-01-09 09:47:28 +03:00
Migrated a lot more components to new DI system
This commit is contained in:
parent
5e6ad14a85
commit
5616d045ab
18 changed files with 237 additions and 213 deletions
|
@ -6,9 +6,8 @@ import React from 'react';
|
|||
import { NavLink } from 'react-router-dom';
|
||||
import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
import DeleteServerButton from '../servers/DeleteServerButton';
|
||||
import './AsideMenu.scss';
|
||||
import { serverType } from '../servers/prop-types';
|
||||
import './AsideMenu.scss';
|
||||
|
||||
const defaultProps = {
|
||||
className: '',
|
||||
|
@ -20,7 +19,8 @@ const propTypes = {
|
|||
showOnMobile: PropTypes.bool,
|
||||
};
|
||||
|
||||
export default function AsideMenu({ selectedServer, className, showOnMobile }) {
|
||||
const AsideMenu = (DeleteServerButton) => {
|
||||
const AsideMenu = ({ selectedServer, className, showOnMobile }) => {
|
||||
const serverId = selectedServer ? selectedServer.id : '';
|
||||
const asideClass = classnames('aside-menu', className, {
|
||||
'aside-menu--hidden': !showOnMobile,
|
||||
|
@ -64,7 +64,12 @@ export default function AsideMenu({ selectedServer, className, showOnMobile }) {
|
|||
</nav>
|
||||
</aside>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
AsideMenu.defaultProps = defaultProps;
|
||||
AsideMenu.propTypes = propTypes;
|
||||
AsideMenu.defaultProps = defaultProps;
|
||||
AsideMenu.propTypes = propTypes;
|
||||
|
||||
return AsideMenu;
|
||||
};
|
||||
|
||||
export default AsideMenu;
|
||||
|
|
|
@ -6,11 +6,10 @@ import { Link } from 'react-router-dom';
|
|||
import { Collapse, Nav, Navbar, NavbarBrand, NavbarToggler, NavItem, NavLink } from 'reactstrap';
|
||||
import classnames from 'classnames';
|
||||
import PropTypes from 'prop-types';
|
||||
import ServersDropdown from '../servers/ServersDropdown';
|
||||
import './MainHeader.scss';
|
||||
import shlinkLogo from './shlink-logo-white.png';
|
||||
import './MainHeader.scss';
|
||||
|
||||
const MainHeader = () => class MainHeaderComponent extends React.Component {
|
||||
const MainHeader = (ServersDropdown) => class MainHeader extends React.Component {
|
||||
static propTypes = {
|
||||
location: PropTypes.object,
|
||||
};
|
||||
|
|
|
@ -7,13 +7,10 @@ import classnames from 'classnames';
|
|||
import * as PropTypes from 'prop-types';
|
||||
import ShortUrlsVisits from '../visits/ShortUrlVisits';
|
||||
import CreateShortUrl from '../short-urls/CreateShortUrl';
|
||||
import ShortUrls from '../short-urls/ShortUrls';
|
||||
import './MenuLayout.scss';
|
||||
import TagsList from '../tags/TagsList';
|
||||
import { serverType } from '../servers/prop-types';
|
||||
import AsideMenu from './AsideMenu';
|
||||
|
||||
export default class MenuLayout extends React.Component {
|
||||
const MenuLayout = (TagsList, ShortUrls, AsideMenu) => class MenuLayout extends React.Component {
|
||||
static propTypes = {
|
||||
match: PropTypes.object,
|
||||
selectServer: PropTypes.func,
|
||||
|
@ -99,4 +96,6 @@ export default class MenuLayout extends React.Component {
|
|||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default MenuLayout;
|
||||
|
|
|
@ -2,37 +2,110 @@ import Bottle from 'bottlejs';
|
|||
import { withRouter } from 'react-router-dom';
|
||||
import { connect } from 'react-redux';
|
||||
import { compose } from 'redux';
|
||||
import { pick } from 'ramda';
|
||||
import { assoc, pick } from 'ramda';
|
||||
import csvjson from 'csvjson';
|
||||
import axios from 'axios';
|
||||
import App from '../App';
|
||||
import ScrollToTop from '../common/ScrollToTop';
|
||||
import MainHeader from '../common/MainHeader';
|
||||
import { resetSelectedServer, selectServer } from '../servers/reducers/selectedServer';
|
||||
import Home from '../common/Home';
|
||||
import MenuLayout from '../common/MenuLayout';
|
||||
import { createServer } from '../servers/reducers/server';
|
||||
import { createServer, createServers, deleteServer, listServers } from '../servers/reducers/server';
|
||||
import CreateServer from '../servers/CreateServer';
|
||||
import store from './store';
|
||||
import ServersDropdown from '../servers/ServersDropdown';
|
||||
import TagsList from '../tags/TagsList';
|
||||
import { filterTags, forceListTags } from '../tags/reducers/tagsList';
|
||||
import ShortUrls from '../short-urls/ShortUrls';
|
||||
import SearchBar from '../short-urls/SearchBar';
|
||||
import { listShortUrls } from '../short-urls/reducers/shortUrlsList';
|
||||
import ShortUrlsList from '../short-urls/ShortUrlsList';
|
||||
import { resetShortUrlParams } from '../short-urls/reducers/shortUrlsListParams';
|
||||
import Tag from '../tags/helpers/Tag';
|
||||
import { ColorGenerator } from '../utils/ColorGenerator';
|
||||
import { Storage } from '../utils/Storage';
|
||||
import ShortUrlsRow from '../short-urls/helpers/ShortUrlsRow';
|
||||
import ShortUrlsRowMenu from '../short-urls/helpers/ShortUrlsRowMenu';
|
||||
import { ShlinkApiClient } from '../api/ShlinkApiClient';
|
||||
import DeleteServerModal from '../servers/DeleteServerModal';
|
||||
import DeleteServerButton from '../servers/DeleteServerButton';
|
||||
import AsideMenu from '../common/AsideMenu';
|
||||
import ImportServersBtn from '../servers/helpers/ImportServersBtn';
|
||||
import { ServersImporter } from '../servers/services/ServersImporter';
|
||||
import { ServersExporter } from '../servers/services/ServersExporter';
|
||||
import { ServersService } from '../servers/services/ServersService';
|
||||
|
||||
const bottle = new Bottle();
|
||||
|
||||
bottle.constant('store', store);
|
||||
bottle.serviceFactory('ScrollToTop', () => withRouter(ScrollToTop));
|
||||
bottle.serviceFactory('MainHeader', () => withRouter(MainHeader()));
|
||||
bottle.serviceFactory('Home', () => connect(pick([ 'servers' ]), { resetSelectedServer })(Home));
|
||||
bottle.serviceFactory(
|
||||
bottle.constant('ScrollToTop', ScrollToTop);
|
||||
bottle.decorator('ScrollToTop', withRouter);
|
||||
|
||||
bottle.serviceFactory('MainHeader', MainHeader, 'ServersDropdown');
|
||||
bottle.decorator('MainHeader', withRouter);
|
||||
|
||||
bottle.serviceFactory('Home', () => Home);
|
||||
bottle.decorator('Home', connect(pick([ 'servers' ]), { resetSelectedServer }));
|
||||
|
||||
bottle.serviceFactory('MenuLayout', MenuLayout, 'TagsList', 'ShortUrls', 'AsideMenu');
|
||||
bottle.decorator(
|
||||
'MenuLayout',
|
||||
() => compose(
|
||||
compose(
|
||||
connect(pick([ 'selectedServer', 'shortUrlsListParams' ]), { selectServer }),
|
||||
withRouter
|
||||
)(MenuLayout)
|
||||
);
|
||||
bottle.serviceFactory(
|
||||
'CreateServer',
|
||||
() => connect(
|
||||
pick([ 'selectedServer' ]),
|
||||
{ createServer, resetSelectedServer }
|
||||
)(CreateServer)
|
||||
)
|
||||
);
|
||||
|
||||
bottle.serviceFactory('CreateServer', CreateServer, 'ImportServersBtn');
|
||||
bottle.decorator('CreateServer', connect(pick([ 'selectedServer' ]), { createServer, resetSelectedServer }));
|
||||
|
||||
bottle.serviceFactory('App', App, 'MainHeader', 'Home', 'MenuLayout', 'CreateServer');
|
||||
|
||||
bottle.serviceFactory('ServersDropdown', ServersDropdown, 'ServersExporter');
|
||||
bottle.decorator('ServersDropdown', connect(pick([ 'servers', 'selectedServer' ]), { listServers, selectServer }));
|
||||
|
||||
bottle.serviceFactory('TagsList', () => TagsList);
|
||||
bottle.decorator('TagsList', connect(pick([ 'tagsList' ]), { forceListTags, filterTags }));
|
||||
|
||||
bottle.serviceFactory('ShortUrls', ShortUrls, 'SearchBar', 'ShortUrlsList');
|
||||
bottle.decorator('ShortUrls', connect(
|
||||
(state) => assoc('shortUrlsList', state.shortUrlsList.shortUrls, state.shortUrlsList)
|
||||
));
|
||||
|
||||
bottle.serviceFactory('SearchBar', SearchBar, 'Tag');
|
||||
bottle.decorator('SearchBar', connect(pick([ 'shortUrlsListParams' ]), { listShortUrls }));
|
||||
|
||||
bottle.serviceFactory('ShortUrlsList', ShortUrlsList, 'ShortUrlsRow');
|
||||
bottle.decorator('ShortUrlsList', connect(
|
||||
pick([ 'selectedServer', 'shortUrlsListParams' ]),
|
||||
{ listShortUrls, resetShortUrlParams }
|
||||
));
|
||||
|
||||
bottle.serviceFactory('Tag', Tag, 'ColorGenerator');
|
||||
|
||||
bottle.constant('localStorage', global.localStorage);
|
||||
bottle.service('Storage', Storage, 'localStorage');
|
||||
bottle.service('ColorGenerator', ColorGenerator, 'Storage');
|
||||
|
||||
bottle.serviceFactory('ShortUrlsRow', ShortUrlsRow, 'Tag', 'ShortUrlsRowMenu');
|
||||
|
||||
bottle.serviceFactory('ShortUrlsRowMenu', () => ShortUrlsRowMenu);
|
||||
|
||||
bottle.constant('axios', axios);
|
||||
bottle.service('ShlinkApiClient', ShlinkApiClient, 'axios');
|
||||
|
||||
bottle.serviceFactory('DeleteServerModal', () => DeleteServerModal);
|
||||
bottle.decorator('DeleteServerModal', compose(withRouter, connect(null, { deleteServer })));
|
||||
|
||||
bottle.serviceFactory('DeleteServerButton', DeleteServerButton, 'DeleteServerModal');
|
||||
bottle.serviceFactory('AsideMenu', AsideMenu, 'DeleteServerButton');
|
||||
|
||||
bottle.serviceFactory('ImportServersBtn', ImportServersBtn, 'ServersImporter');
|
||||
bottle.decorator('ImportServersBtn', connect(null, { createServers }));
|
||||
|
||||
bottle.constant('csvjson', csvjson);
|
||||
bottle.constant('window', global.window);
|
||||
bottle.service('ServersImporter', ServersImporter, 'csvjson');
|
||||
bottle.service('ServersService', ServersService, 'Storage');
|
||||
bottle.service('ServersExporter', ServersExporter, 'ServersService', 'window', 'csvjson');
|
||||
|
||||
export default bottle.container;
|
||||
|
|
|
@ -6,11 +6,12 @@ import { BrowserRouter } from 'react-router-dom';
|
|||
import { homepage } from '../package.json';
|
||||
import registerServiceWorker from './registerServiceWorker';
|
||||
import container from './container';
|
||||
import store from './container/store';
|
||||
import '../node_modules/react-datepicker/dist/react-datepicker.css';
|
||||
import './common/react-tagsinput.scss';
|
||||
import './index.scss';
|
||||
|
||||
const { App, ScrollToTop, store } = container;
|
||||
const { App, ScrollToTop } = container;
|
||||
|
||||
render(
|
||||
<Provider store={store}>
|
||||
|
|
|
@ -4,11 +4,10 @@ import { v4 as uuid } from 'uuid';
|
|||
import PropTypes from 'prop-types';
|
||||
import { stateFlagTimeout } from '../utils/utils';
|
||||
import './CreateServer.scss';
|
||||
import ImportServersBtn from './helpers/ImportServersBtn';
|
||||
|
||||
const SHOW_IMPORT_MSG_TIME = 4000;
|
||||
|
||||
export default class CreateServer extends React.Component {
|
||||
const CreateServer = (ImportServersBtn) => class CreateServer extends React.Component {
|
||||
static propTypes = {
|
||||
createServer: PropTypes.func,
|
||||
history: PropTypes.shape({
|
||||
|
@ -88,4 +87,6 @@ export default class CreateServer extends React.Component {
|
|||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default CreateServer;
|
||||
|
|
|
@ -2,10 +2,9 @@ import deleteIcon from '@fortawesome/fontawesome-free-solid/faMinusCircle';
|
|||
import FontAwesomeIcon from '@fortawesome/react-fontawesome';
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import DeleteServerModal from './DeleteServerModal';
|
||||
import { serverType } from './prop-types';
|
||||
|
||||
export default class DeleteServerButton extends React.Component {
|
||||
const DeleteServerButton = (DeleteServerModal) => class DeleteServerButton extends React.Component {
|
||||
static propTypes = {
|
||||
server: serverType,
|
||||
className: PropTypes.string,
|
||||
|
@ -36,4 +35,6 @@ export default class DeleteServerButton extends React.Component {
|
|||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default DeleteServerButton;
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
import { Modal, ModalBody, ModalFooter, ModalHeader } from 'reactstrap';
|
||||
import { compose } from 'redux';
|
||||
import { deleteServer } from './reducers/server';
|
||||
import { serverType } from './prop-types';
|
||||
|
||||
const propTypes = {
|
||||
|
@ -17,7 +13,7 @@ const propTypes = {
|
|||
}),
|
||||
};
|
||||
|
||||
export const DeleteServerModalComponent = ({ server, toggle, isOpen, deleteServer, history }) => {
|
||||
const DeleteServerModal = ({ server, toggle, isOpen, deleteServer, history }) => {
|
||||
const closeModal = () => {
|
||||
deleteServer(server);
|
||||
toggle();
|
||||
|
@ -42,11 +38,6 @@ export const DeleteServerModalComponent = ({ server, toggle, isOpen, deleteServe
|
|||
);
|
||||
};
|
||||
|
||||
DeleteServerModalComponent.propTypes = propTypes;
|
||||
|
||||
const DeleteServerModal = compose(
|
||||
withRouter,
|
||||
connect(null, { deleteServer })
|
||||
)(DeleteServerModalComponent);
|
||||
DeleteServerModal.propTypes = propTypes;
|
||||
|
||||
export default DeleteServerModal;
|
||||
|
|
|
@ -1,30 +1,20 @@
|
|||
import { isEmpty, pick, values } from 'ramda';
|
||||
import { isEmpty, values } from 'ramda';
|
||||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { DropdownItem, DropdownMenu, DropdownToggle, UncontrolledDropdown } from 'reactstrap';
|
||||
import PropTypes from 'prop-types';
|
||||
import { selectServer } from '../servers/reducers/selectedServer';
|
||||
import serversExporter from '../servers/services/ServersExporter';
|
||||
import { listServers } from './reducers/server';
|
||||
import { serverType } from './prop-types';
|
||||
|
||||
export class ServersDropdownComponent extends React.Component {
|
||||
static defaultProps = {
|
||||
serversExporter,
|
||||
};
|
||||
const ServersDropdown = (serversExporter) => class ServersDropdown extends React.Component {
|
||||
static propTypes = {
|
||||
servers: PropTypes.object,
|
||||
serversExporter: PropTypes.shape({
|
||||
exportServers: PropTypes.func,
|
||||
}),
|
||||
selectedServer: serverType,
|
||||
selectServer: PropTypes.func,
|
||||
listServers: PropTypes.func,
|
||||
};
|
||||
|
||||
renderServers = () => {
|
||||
const { servers, selectedServer, selectServer, serversExporter } = this.props;
|
||||
const { servers, selectedServer, selectServer } = this.props;
|
||||
|
||||
if (isEmpty(servers)) {
|
||||
return <DropdownItem disabled><i>Add a server first...</i></DropdownItem>;
|
||||
|
@ -68,11 +58,6 @@ export class ServersDropdownComponent extends React.Component {
|
|||
</UncontrolledDropdown>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const ServersDropdown = connect(
|
||||
pick([ 'servers', 'selectedServer' ]),
|
||||
{ listServers, selectServer }
|
||||
)(ServersDropdownComponent);
|
||||
};
|
||||
|
||||
export default ServersDropdown;
|
||||
|
|
|
@ -1,20 +1,15 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { UncontrolledTooltip } from 'reactstrap';
|
||||
import { assoc } from 'ramda';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import PropTypes from 'prop-types';
|
||||
import { createServers } from '../reducers/server';
|
||||
import serversImporter, { serversImporterType } from '../services/ServersImporter';
|
||||
|
||||
export class ImportServersBtnComponent extends React.Component {
|
||||
const ImportServersBtn = (serversImporter) => class ImportServersBtn extends React.Component {
|
||||
static defaultProps = {
|
||||
serversImporter,
|
||||
onImport: () => ({}),
|
||||
};
|
||||
static propTypes = {
|
||||
onImport: PropTypes.func,
|
||||
serversImporter: serversImporterType,
|
||||
createServers: PropTypes.func,
|
||||
fileRef: PropTypes.oneOfType([ PropTypes.object, PropTypes.node ]),
|
||||
};
|
||||
|
@ -25,7 +20,8 @@ export class ImportServersBtnComponent extends React.Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
const { serversImporter: { importServersFromFile }, onImport, createServers } = this.props;
|
||||
const { importServersFromFile } = serversImporter;
|
||||
const { onImport, createServers } = this.props;
|
||||
const onChange = (e) =>
|
||||
importServersFromFile(e.target.files[0])
|
||||
.then((servers) => servers.map((server) => assoc('id', uuid(), server)))
|
||||
|
@ -56,8 +52,6 @@ export class ImportServersBtnComponent extends React.Component {
|
|||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const ImportServersBtn = connect(null, { createServers })(ImportServersBtnComponent);
|
||||
};
|
||||
|
||||
export default ImportServersBtn;
|
||||
|
|
|
@ -1,21 +1,19 @@
|
|||
import tagsIcon from '@fortawesome/fontawesome-free-solid/faTags';
|
||||
import FontAwesomeIcon from '@fortawesome/react-fontawesome';
|
||||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { isEmpty, pick } from 'ramda';
|
||||
import { isEmpty } from 'ramda';
|
||||
import PropTypes from 'prop-types';
|
||||
import Tag from '../tags/helpers/Tag';
|
||||
import SearchField from '../utils/SearchField';
|
||||
import { listShortUrls } from './reducers/shortUrlsList';
|
||||
import './SearchBar.scss';
|
||||
import { shortUrlsListParamsType } from './reducers/shortUrlsListParams';
|
||||
import './SearchBar.scss';
|
||||
|
||||
const propTypes = {
|
||||
listShortUrls: PropTypes.func,
|
||||
shortUrlsListParams: shortUrlsListParamsType,
|
||||
};
|
||||
|
||||
export function SearchBarComponent({ listShortUrls, shortUrlsListParams }) {
|
||||
const SearchBar = (Tag) => {
|
||||
const SearchBar = ({ listShortUrls, shortUrlsListParams }) => {
|
||||
const selectedTags = shortUrlsListParams.tags || [];
|
||||
|
||||
return (
|
||||
|
@ -46,10 +44,11 @@ export function SearchBarComponent({ listShortUrls, shortUrlsListParams }) {
|
|||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
SearchBarComponent.propTypes = propTypes;
|
||||
SearchBar.propTypes = propTypes;
|
||||
|
||||
const SearchBar = connect(pick([ 'shortUrlsListParams' ]), { listShortUrls })(SearchBarComponent);
|
||||
return SearchBar;
|
||||
};
|
||||
|
||||
export default SearchBar;
|
||||
|
|
|
@ -1,27 +1,21 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { assoc } from 'ramda';
|
||||
import Paginator from './Paginator';
|
||||
import SearchBar from './SearchBar';
|
||||
import ShortUrlsList from './ShortUrlsList';
|
||||
|
||||
export function ShortUrlsComponent(props) {
|
||||
const { match: { params } } = props;
|
||||
const ShortUrls = (SearchBar, ShortUrlsList) => (props) => {
|
||||
const { match: { params }, shortUrlsList } = props;
|
||||
const { page, serverId } = params;
|
||||
const { data = [], pagination } = shortUrlsList;
|
||||
|
||||
// Using a key on a component makes react to create a new instance every time the key changes
|
||||
const urlsListKey = `${params.serverId}_${params.page}`;
|
||||
const urlsListKey = `${serverId}_${page}`;
|
||||
|
||||
return (
|
||||
<div className="shlink-container">
|
||||
<div className="form-group"><SearchBar /></div>
|
||||
<ShortUrlsList {...props} shortUrlsList={props.shortUrlsList.data || []} key={urlsListKey} />
|
||||
<Paginator paginator={props.shortUrlsList.pagination} serverId={props.match.params.serverId} />
|
||||
<ShortUrlsList {...props} shortUrlsList={data} key={urlsListKey} />
|
||||
<Paginator paginator={pagination} serverId={serverId} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const ShortUrls = connect(
|
||||
(state) => assoc('shortUrlsList', state.shortUrlsList.shortUrls, state.shortUrlsList)
|
||||
)(ShortUrlsComponent);
|
||||
};
|
||||
|
||||
export default ShortUrls;
|
||||
|
|
|
@ -1,17 +1,15 @@
|
|||
import caretDownIcon from '@fortawesome/fontawesome-free-solid/faCaretDown';
|
||||
import caretUpIcon from '@fortawesome/fontawesome-free-solid/faCaretUp';
|
||||
import FontAwesomeIcon from '@fortawesome/react-fontawesome';
|
||||
import { head, isEmpty, keys, pick, values } from 'ramda';
|
||||
import { head, isEmpty, keys, values } from 'ramda';
|
||||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import qs from 'qs';
|
||||
import PropTypes from 'prop-types';
|
||||
import { serverType } from '../servers/prop-types';
|
||||
import SortingDropdown from '../utils/SortingDropdown';
|
||||
import { determineOrderDir } from '../utils/utils';
|
||||
import { ShortUrlsRow } from './helpers/ShortUrlsRow';
|
||||
import { listShortUrls, shortUrlType } from './reducers/shortUrlsList';
|
||||
import { resetShortUrlParams, shortUrlsListParamsType } from './reducers/shortUrlsListParams';
|
||||
import { shortUrlType } from './reducers/shortUrlsList';
|
||||
import { shortUrlsListParamsType } from './reducers/shortUrlsListParams';
|
||||
import './ShortUrlsList.scss';
|
||||
|
||||
const SORTABLE_FIELDS = {
|
||||
|
@ -21,7 +19,7 @@ const SORTABLE_FIELDS = {
|
|||
visits: 'Visits',
|
||||
};
|
||||
|
||||
export class ShortUrlsListComponent extends React.Component {
|
||||
const ShortUrlsList = (ShortUrlsRow) => class ShortUrlsList extends React.Component {
|
||||
static propTypes = {
|
||||
listShortUrls: PropTypes.func,
|
||||
resetShortUrlParams: PropTypes.func,
|
||||
|
@ -167,11 +165,6 @@ export class ShortUrlsListComponent extends React.Component {
|
|||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const ShortUrlsList = connect(
|
||||
pick([ 'selectedServer', 'shortUrlsListParams' ]),
|
||||
{ listShortUrls, resetShortUrlParams }
|
||||
)(ShortUrlsListComponent);
|
||||
};
|
||||
|
||||
export default ShortUrlsList;
|
||||
|
|
|
@ -2,16 +2,14 @@ import { isEmpty } from 'ramda';
|
|||
import React from 'react';
|
||||
import Moment from 'react-moment';
|
||||
import PropTypes from 'prop-types';
|
||||
import Tag from '../../tags/helpers/Tag';
|
||||
import { shortUrlsListParamsType } from '../reducers/shortUrlsListParams';
|
||||
import { serverType } from '../../servers/prop-types';
|
||||
import ExternalLink from '../../utils/ExternalLink';
|
||||
import { shortUrlType } from '../reducers/shortUrlsList';
|
||||
import { stateFlagTimeout } from '../../utils/utils';
|
||||
import { ShortUrlsRowMenu } from './ShortUrlsRowMenu';
|
||||
import './ShortUrlsRow.scss';
|
||||
|
||||
export class ShortUrlsRow extends React.Component {
|
||||
const ShortUrlsRow = (Tag, ShortUrlsRowMenu) => class ShortUrlsRow extends React.Component {
|
||||
static propTypes = {
|
||||
refreshList: PropTypes.func,
|
||||
shortUrlsListParams: shortUrlsListParamsType,
|
||||
|
@ -72,4 +70,6 @@ export class ShortUrlsRow extends React.Component {
|
|||
</tr>
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default ShortUrlsRow;
|
||||
|
|
|
@ -19,7 +19,7 @@ import EditTagsModal from './EditTagsModal';
|
|||
import DeleteShortUrlModal from './DeleteShortUrlModal';
|
||||
import './ShortUrlsRowMenu.scss';
|
||||
|
||||
export class ShortUrlsRowMenu extends React.Component {
|
||||
export default class ShortUrlsRowMenu extends React.Component {
|
||||
static propTypes = {
|
||||
completeShortUrl: PropTypes.string,
|
||||
onCopyToClipboard: PropTypes.func,
|
||||
|
|
|
@ -1,16 +1,14 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { pick, splitEvery } from 'ramda';
|
||||
import { splitEvery } from 'ramda';
|
||||
import PropTypes from 'prop-types';
|
||||
import MuttedMessage from '../utils/MuttedMessage';
|
||||
import SearchField from '../utils/SearchField';
|
||||
import { filterTags, forceListTags } from './reducers/tagsList';
|
||||
import TagCard from './TagCard';
|
||||
|
||||
const { ceil } = Math;
|
||||
const TAGS_GROUPS_AMOUNT = 4;
|
||||
|
||||
export class TagsListComponent extends React.Component {
|
||||
export default class TagsList extends React.Component {
|
||||
static propTypes = {
|
||||
filterTags: PropTypes.func,
|
||||
forceListTags: PropTypes.func,
|
||||
|
@ -83,7 +81,3 @@ export class TagsListComponent extends React.Component {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
const TagsList = connect(pick([ 'tagsList' ]), { forceListTags, filterTags })(TagsListComponent);
|
||||
|
||||
export default TagsList;
|
||||
|
|
|
@ -1,31 +1,23 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import colorGenerator, { colorGeneratorType } from '../../utils/ColorGenerator';
|
||||
import './Tag.scss';
|
||||
|
||||
const propTypes = {
|
||||
colorGenerator: colorGeneratorType,
|
||||
text: PropTypes.string,
|
||||
children: PropTypes.node,
|
||||
clearable: PropTypes.bool,
|
||||
onClick: PropTypes.func,
|
||||
onClose: PropTypes.func,
|
||||
};
|
||||
const defaultProps = {
|
||||
colorGenerator,
|
||||
};
|
||||
|
||||
export default function Tag(
|
||||
{
|
||||
colorGenerator,
|
||||
const Tag = (colorGenerator) => {
|
||||
const Tag = ({
|
||||
text,
|
||||
children,
|
||||
clearable,
|
||||
onClick = () => ({}),
|
||||
onClose = () => ({}),
|
||||
}
|
||||
) {
|
||||
return (
|
||||
onClick = () => {},
|
||||
onClose = () => {},
|
||||
}) => (
|
||||
<span
|
||||
className="badge tag"
|
||||
style={{ backgroundColor: colorGenerator.getColorForKey(text), cursor: clearable ? 'auto' : 'pointer' }}
|
||||
|
@ -35,7 +27,10 @@ export default function Tag(
|
|||
{clearable && <span className="close tag__close-selected-tag" onClick={onClose}>×</span>}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
Tag.defaultProps = defaultProps;
|
||||
Tag.propTypes = propTypes;
|
||||
Tag.propTypes = propTypes;
|
||||
|
||||
return Tag;
|
||||
};
|
||||
|
||||
export default Tag;
|
||||
|
|
|
@ -2,7 +2,7 @@ import { identity, values } from 'ramda';
|
|||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
import { DropdownItem, DropdownToggle } from 'reactstrap';
|
||||
import { ServersDropdownComponent } from '../../src/servers/ServersDropdown';
|
||||
import ServersDropdown from '../../src/servers/ServersDropdown';
|
||||
|
||||
describe('<ServersDropdown />', () => {
|
||||
let wrapped;
|
||||
|
@ -13,7 +13,7 @@ describe('<ServersDropdown />', () => {
|
|||
};
|
||||
|
||||
beforeEach(() => {
|
||||
wrapped = shallow(<ServersDropdownComponent servers={servers} listServers={identity} />);
|
||||
wrapped = shallow(<ServersDropdown servers={servers} listServers={identity} />);
|
||||
});
|
||||
afterEach(() => wrapped.unmount());
|
||||
|
||||
|
@ -31,7 +31,7 @@ describe('<ServersDropdown />', () => {
|
|||
});
|
||||
|
||||
it('contains a message when no servers exist yet', () => {
|
||||
wrapped = shallow(<ServersDropdownComponent servers={{}} listServers={identity} />);
|
||||
wrapped = shallow(<ServersDropdown servers={{}} listServers={identity} />);
|
||||
const item = wrapped.find(DropdownItem);
|
||||
|
||||
expect(item).toHaveLength(1);
|
||||
|
|
Loading…
Reference in a new issue