From a1eadf767eb889a23d664e158ee71035749037d6 Mon Sep 17 00:00:00 2001 From: Alejandro Celaya Date: Wed, 15 Aug 2018 18:44:54 +0200 Subject: [PATCH] Updated short URL tags adding real behavior --- src/api/ShlinkApiClient.js | 5 ++ src/reducers/index.js | 4 +- src/short-urls/helpers/EditTagsModal.js | 40 ++++++++++++++-- src/short-urls/reducers/shortUrlTags.js | 63 +++++++++++++++++++++++++ 4 files changed, 106 insertions(+), 6 deletions(-) create mode 100644 src/short-urls/reducers/shortUrlTags.js diff --git a/src/api/ShlinkApiClient.js b/src/api/ShlinkApiClient.js index f5227652..7714dd3b 100644 --- a/src/api/ShlinkApiClient.js +++ b/src/api/ShlinkApiClient.js @@ -44,6 +44,11 @@ export class ShlinkApiClient { .then(resp => resp.data) .catch(e => this._handleAuthError(e, this.getShortUrl, [shortCode])); + updateShortUrlTags = (shortCode, tags) => + this._performRequest(`/short-codes/${shortCode}/tags`, 'PUT', {}, { tags }) + .then(resp => resp.data.tags) + .catch(e => this._handleAuthError(e, this.updateShortUrlTags, [shortCode, tags])); + _performRequest = async (url, method = 'GET', params = {}, data = {}) => { if (isEmpty(this._token)) { this._token = await this._authenticate(); diff --git a/src/reducers/index.js b/src/reducers/index.js index 6aae91c8..20c0c481 100644 --- a/src/reducers/index.js +++ b/src/reducers/index.js @@ -6,6 +6,7 @@ import shortUrlsListReducer from '../short-urls/reducers/shortUrlsList'; import shortUrlsListParamsReducer from '../short-urls/reducers/shortUrlsListParams'; import shortUrlCreationResultReducer from '../short-urls/reducers/shortUrlCreationResult'; import shortUrlVisitsReducer from '../short-urls/reducers/shortUrlVisits'; +import shortUrlTagsReducer from '../short-urls/reducers/shortUrlTags'; export default combineReducers({ servers: serversReducer, @@ -13,5 +14,6 @@ export default combineReducers({ shortUrlsList: shortUrlsListReducer, shortUrlsListParams: shortUrlsListParamsReducer, shortUrlCreationResult: shortUrlCreationResultReducer, - shortUrlVisits: shortUrlVisitsReducer + shortUrlVisits: shortUrlVisitsReducer, + shortUrlTags: shortUrlTagsReducer, }); diff --git a/src/short-urls/helpers/EditTagsModal.js b/src/short-urls/helpers/EditTagsModal.js index e85292e8..2f413fa1 100644 --- a/src/short-urls/helpers/EditTagsModal.js +++ b/src/short-urls/helpers/EditTagsModal.js @@ -1,27 +1,57 @@ import React from 'react'; +import { connect } from 'react-redux'; import { Modal, ModalBody, ModalFooter, ModalHeader } from 'reactstrap'; import TagsSelector from '../../utils/TagsSelector'; +import PropTypes from 'prop-types'; +import { editShortUrlTags, shortUrlTagsType } from '../reducers/shortUrlTags'; +import { pick } from 'ramda'; + +const propTypes = { + isOpen: PropTypes.bool.isRequired, + toggle: PropTypes.func.isRequired, + url: PropTypes.string.isRequired, + shortUrl: PropTypes.shape({ + tags: PropTypes.arrayOf(PropTypes.string), + }).isRequired, + shortUrlTags: shortUrlTagsType, +}; + +export class EditTagsModal extends React.Component { + saveTags = () => { + const { editShortUrlTags, shortUrl, toggle } = this.props; + editShortUrlTags(shortUrl.shortCode, this.state.tags).then(toggle); + }; -export default class EditTagsModal extends React.Component { constructor(props) { super(props); this.state = { tags: props.shortUrl.tags }; } render() { - const { isOpen, toggle, url } = this.props; - const changeTags = tags => this.setState({ tags }); + const { isOpen, toggle, url, shortUrlTags } = this.props; return ( Edit tags for {url} - + this.setState({ tags })} /> - + + ); } } + +EditTagsModal.propTypes = propTypes; + +export default connect(pick(['shortUrlTags']), { editShortUrlTags })(EditTagsModal); diff --git a/src/short-urls/reducers/shortUrlTags.js b/src/short-urls/reducers/shortUrlTags.js new file mode 100644 index 00000000..c12d87af --- /dev/null +++ b/src/short-urls/reducers/shortUrlTags.js @@ -0,0 +1,63 @@ +import ShlinkApiClient from '../../api/ShlinkApiClient'; +import { curry } from 'ramda'; +import PropTypes from 'prop-types'; +import { _listShortUrls } from './shortUrlsList'; + +export const EDIT_SHORT_URL_TAGS_START = 'shlink/shortUrlTags/EDIT_SHORT_URL_TAGS_START'; +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 shortUrlTagsType = PropTypes.shape({ + shortCode: PropTypes.string, + tags: PropTypes.arrayOf(PropTypes.string).isRequired, + saving: PropTypes.bool.isRequired, + error: PropTypes.bool.isRequired, +}); + +const defaultState = { + shortCode: null, + tags: [], + saving: false, + error: false, +}; + +export default function reducer(state = defaultState, action) { + switch (action.type) { + case EDIT_SHORT_URL_TAGS_START: + return { + ...state, + saving: true, + error: false, + }; + case EDIT_SHORT_URL_TAGS_ERROR: + return { + ...state, + saving: false, + error: true, + }; + case EDIT_SHORT_URL_TAGS: + return { + shortCode: action.shortCode, + tags: action.tags, + saving: false, + error: false, + }; + default: + return state; + } +} + +export const _editShortUrlTags = (ShlinkApiClient, shortCode, tags) => async (dispatch, getState) => { + dispatch({ type: EDIT_SHORT_URL_TAGS_START }); + + try { + await ShlinkApiClient.updateShortUrlTags(shortCode, tags); + dispatch({ tags, shortCode, type: EDIT_SHORT_URL_TAGS }); + + const { shortUrlsListParams } = getState(); + await _listShortUrls(ShlinkApiClient, shortUrlsListParams)(dispatch); + } catch (e) { + dispatch({ type: EDIT_SHORT_URL_TAGS_ERROR }); + } +}; +export const editShortUrlTags = curry(_editShortUrlTags)(ShlinkApiClient);