Prevented short URLs list to be reloaded when tags are edited

This commit is contained in:
Alejandro Celaya 2018-08-18 17:14:33 +02:00
parent b5de9bf523
commit 680d80d753
4 changed files with 34 additions and 14 deletions

View file

@ -3,9 +3,13 @@ import { connect } from 'react-redux';
import { Modal, ModalBody, ModalFooter, ModalHeader } from 'reactstrap'; import { Modal, ModalBody, ModalFooter, ModalHeader } from 'reactstrap';
import TagsSelector from '../../utils/TagsSelector'; import TagsSelector from '../../utils/TagsSelector';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { editShortUrlTags, resetShortUrlsTags, shortUrlTagsType } from '../reducers/shortUrlTags'; import {
editShortUrlTags,
resetShortUrlsTags,
shortUrlTagsType,
shortUrlTagsEdited
} from '../reducers/shortUrlTags';
import { pick } from 'ramda'; import { pick } from 'ramda';
import { refreshShortUrls } from '../reducers/shortUrlsList';
const propTypes = { const propTypes = {
isOpen: PropTypes.bool.isRequired, isOpen: PropTypes.bool.isRequired,
@ -13,6 +17,7 @@ const propTypes = {
url: PropTypes.string.isRequired, url: PropTypes.string.isRequired,
shortUrl: PropTypes.shape({ shortUrl: PropTypes.shape({
tags: PropTypes.arrayOf(PropTypes.string), tags: PropTypes.arrayOf(PropTypes.string),
shortCode: PropTypes.string,
}).isRequired, }).isRequired,
shortUrlTags: shortUrlTagsType, shortUrlTags: shortUrlTagsType,
}; };
@ -32,7 +37,9 @@ export class EditTagsModal extends React.Component {
return; return;
} }
this.props.refreshShortUrls(); const { shortUrlTagsEdited, shortUrl } = this.props;
const { tags } = this.state;
shortUrlTagsEdited(shortUrl.shortCode, tags);
}; };
componentDidMount() { componentDidMount() {
@ -51,7 +58,9 @@ export class EditTagsModal extends React.Component {
return ( return (
<Modal isOpen={isOpen} toggle={toggle} centered onClosed={this.refreshShortUrls}> <Modal isOpen={isOpen} toggle={toggle} centered onClosed={this.refreshShortUrls}>
<ModalHeader toggle={toggle}>Edit tags for <a target="_blank" href={url}>{url}</a></ModalHeader> <ModalHeader toggle={toggle}>
Edit tags for <a target="_blank" href={url}>{url}</a>
</ModalHeader>
<ModalBody> <ModalBody>
<TagsSelector tags={this.state.tags} onChange={tags => this.setState({ tags })} /> <TagsSelector tags={this.state.tags} onChange={tags => this.setState({ tags })} />
{shortUrlTags.error && ( {shortUrlTags.error && (
@ -80,5 +89,5 @@ EditTagsModal.propTypes = propTypes;
export default connect( export default connect(
pick(['shortUrlTags']), pick(['shortUrlTags']),
{ editShortUrlTags, resetShortUrlsTags, refreshShortUrls } { editShortUrlTags, resetShortUrlsTags, shortUrlTagsEdited }
)(EditTagsModal); )(EditTagsModal);

View file

@ -6,6 +6,7 @@ export const EDIT_SHORT_URL_TAGS_START = 'shlink/shortUrlTags/EDIT_SHORT_URL_TAG
export const EDIT_SHORT_URL_TAGS_ERROR = 'shlink/shortUrlTags/EDIT_SHORT_URL_TAGS_ERROR'; export const EDIT_SHORT_URL_TAGS_ERROR = 'shlink/shortUrlTags/EDIT_SHORT_URL_TAGS_ERROR';
export const EDIT_SHORT_URL_TAGS = 'shlink/shortUrlTags/EDIT_SHORT_URL_TAGS'; export const EDIT_SHORT_URL_TAGS = 'shlink/shortUrlTags/EDIT_SHORT_URL_TAGS';
export const RESET_EDIT_SHORT_URL_TAGS = 'shlink/shortUrlTags/RESET_EDIT_SHORT_URL_TAGS'; export const RESET_EDIT_SHORT_URL_TAGS = 'shlink/shortUrlTags/RESET_EDIT_SHORT_URL_TAGS';
export const SHORT_URL_TAGS_EDITED = 'shlink/shortUrlTags/SHORT_URL_TAGS_EDITED';
export const shortUrlTagsType = PropTypes.shape({ export const shortUrlTagsType = PropTypes.shape({
shortCode: PropTypes.string, shortCode: PropTypes.string,
@ -64,3 +65,9 @@ export const _editShortUrlTags = (ShlinkApiClient, shortCode, tags) => async (di
export const editShortUrlTags = curry(_editShortUrlTags)(ShlinkApiClient); export const editShortUrlTags = curry(_editShortUrlTags)(ShlinkApiClient);
export const resetShortUrlsTags = () => ({ type: RESET_EDIT_SHORT_URL_TAGS }); export const resetShortUrlsTags = () => ({ type: RESET_EDIT_SHORT_URL_TAGS });
export const shortUrlTagsEdited = (shortCode, tags) => ({
tags,
shortCode,
type: SHORT_URL_TAGS_EDITED,
});

View file

@ -1,4 +1,6 @@
import ShlinkApiClient from '../../api/ShlinkApiClient'; import ShlinkApiClient from '../../api/ShlinkApiClient';
import { SHORT_URL_TAGS_EDITED } from './shortUrlTags';
import { assoc, assocPath } from 'ramda';
const LIST_SHORT_URLS_START = 'shlink/shortUrlsList/LIST_SHORT_URLS_START'; const LIST_SHORT_URLS_START = 'shlink/shortUrlsList/LIST_SHORT_URLS_START';
const LIST_SHORT_URLS_ERROR = 'shlink/shortUrlsList/LIST_SHORT_URLS_ERROR'; const LIST_SHORT_URLS_ERROR = 'shlink/shortUrlsList/LIST_SHORT_URLS_ERROR';
@ -25,6 +27,13 @@ export default function reducer(state = initialState, action) {
error: true, error: true,
shortUrls: [] shortUrls: []
}; };
case SHORT_URL_TAGS_EDITED:
const { data } = state.shortUrls;
return assocPath(['shortUrls', 'data'], data.map(shortUrl =>
shortUrl.shortCode === action.shortCode
? assoc('tags', action.tags, shortUrl)
: shortUrl
), state);
default: default:
return state; return state;
} }
@ -41,9 +50,3 @@ export const _listShortUrls = (ShlinkApiClient, params = {}) => async dispatch =
} }
}; };
export const listShortUrls = (params = {}) => _listShortUrls(ShlinkApiClient, params); export const listShortUrls = (params = {}) => _listShortUrls(ShlinkApiClient, params);
export const _refreshShortUrls = ShlinkApiClient => async (dispatch, getState) => {
const { shortUrlsListParams } = getState();
await _listShortUrls(ShlinkApiClient, shortUrlsListParams)(dispatch);
};
export const refreshShortUrls = () => _refreshShortUrls(ShlinkApiClient);

View file

@ -1,6 +1,7 @@
import { shallow } from 'enzyme' import { shallow } from 'enzyme'
import React from 'react' import React from 'react'
import AsideMenu from '../../src/common/AsideMenu' import AsideMenu from '../../src/common/AsideMenu'
import { NavLink } from 'react-router-dom';
describe('<AsideMenu />', () => { describe('<AsideMenu />', () => {
let wrapped; let wrapped;
@ -12,10 +13,10 @@ describe('<AsideMenu />', () => {
wrapped.unmount(); wrapped.unmount();
}); });
it('contains links to selected server', () => { it('contains links to different sections', () => {
const links = wrapped.find('NavLink'); const links = wrapped.find(NavLink);
expect(links).toHaveLength(2); expect(links).toHaveLength(3);
links.forEach(link => expect(link.prop('to')).toContain('abc123')); links.forEach(link => expect(link.prop('to')).toContain('abc123'));
}); });