mirror of
https://github.com/shlinkio/shlink-web-client.git
synced 2024-12-23 17:40:23 +03:00
Merge pull request #206 from acelaya-forks/feature/match-domain
Feature/match domain
This commit is contained in:
commit
da54a72b3e
9 changed files with 35 additions and 17 deletions
|
@ -4,7 +4,7 @@ All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org).
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org).
|
||||||
|
|
||||||
## [Unreleased]
|
## 2.3.1 - 2020-02-08
|
||||||
|
|
||||||
#### Added
|
#### Added
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
* [#193](https://github.com/shlinkio/shlink-web-client/issues/193) Fixed `maxVisits` being set to 0 when trying to reset it from having a value to `null`.
|
* [#193](https://github.com/shlinkio/shlink-web-client/issues/193) Fixed `maxVisits` being set to 0 when trying to reset it from having a value to `null`.
|
||||||
* [#196](https://github.com/shlinkio/shlink-web-client/issues/196) Included apache `.htaccess` file which takes care of falling back to index.html when reloading the page on a client-side handled route.
|
* [#196](https://github.com/shlinkio/shlink-web-client/issues/196) Included apache `.htaccess` file which takes care of falling back to index.html when reloading the page on a client-side handled route.
|
||||||
* [#179](https://github.com/shlinkio/shlink-web-client/issues/179) Ensured domain is provided to Shlink server when editing, deleting or fetching short URLs which do not belong to default domain.
|
* [#179](https://github.com/shlinkio/shlink-web-client/issues/179) Ensured domain is provided to Shlink server when editing, deleting or fetching short URLs which do not belong to default domain.
|
||||||
|
* [#202](https://github.com/shlinkio/shlink-web-client/issues/202) Fixed domain not passed when dispatching actions that affect a single short URL (edit tags, edit meta and delete), which cased the list not to be properly updated.
|
||||||
|
|
||||||
|
|
||||||
## 2.3.0 - 2020-01-19
|
## 2.3.0 - 2020-01-19
|
||||||
|
|
|
@ -37,7 +37,7 @@ export const deleteShortUrl = (buildShlinkApiClient) => (shortCode, domain) => a
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await deleteShortUrl(shortCode, domain);
|
await deleteShortUrl(shortCode, domain);
|
||||||
dispatch({ type: SHORT_URL_DELETED, shortCode });
|
dispatch({ type: SHORT_URL_DELETED, shortCode, domain });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
dispatch({ type: DELETE_SHORT_URL_ERROR, errorData: e.response.data });
|
dispatch({ type: DELETE_SHORT_URL_ERROR, errorData: e.response.data });
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@ export const editShortUrlMeta = (buildShlinkApiClient) => (shortCode, domain, me
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await updateShortUrlMeta(shortCode, domain, meta);
|
await updateShortUrlMeta(shortCode, domain, meta);
|
||||||
dispatch({ shortCode, meta, type: SHORT_URL_META_EDITED });
|
dispatch({ shortCode, meta, domain, type: SHORT_URL_META_EDITED });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
dispatch({ type: EDIT_SHORT_URL_META_ERROR });
|
dispatch({ type: EDIT_SHORT_URL_META_ERROR });
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ export const editShortUrlTags = (buildShlinkApiClient) => (shortCode, domain, ta
|
||||||
try {
|
try {
|
||||||
const normalizedTags = await updateShortUrlTags(shortCode, domain, tags);
|
const normalizedTags = await updateShortUrlTags(shortCode, domain, tags);
|
||||||
|
|
||||||
dispatch({ tags: normalizedTags, shortCode, type: SHORT_URL_TAGS_EDITED });
|
dispatch({ tags: normalizedTags, shortCode, domain, type: SHORT_URL_TAGS_EDITED });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
dispatch({ type: EDIT_SHORT_URL_TAGS_ERROR });
|
dispatch({ type: EDIT_SHORT_URL_TAGS_ERROR });
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { handleActions } from 'redux-actions';
|
import { handleActions } from 'redux-actions';
|
||||||
import { assoc, assocPath, propEq, reject } from 'ramda';
|
import { assoc, assocPath, isNil, reject } from 'ramda';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { SHORT_URL_TAGS_EDITED } from './shortUrlTags';
|
import { SHORT_URL_TAGS_EDITED } from './shortUrlTags';
|
||||||
import { SHORT_URL_DELETED } from './shortUrlDeletion';
|
import { SHORT_URL_DELETED } from './shortUrlDeletion';
|
||||||
|
@ -27,10 +27,18 @@ const initialState = {
|
||||||
error: false,
|
error: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
const setPropFromActionOnMatchingShortUrl = (prop) => (state, { shortCode, [prop]: propValue }) => assocPath(
|
const shortUrlMatches = (shortUrl, shortCode, domain) => {
|
||||||
|
if (isNil(domain)) {
|
||||||
|
return shortUrl.shortCode === shortCode && !shortUrl.domain;
|
||||||
|
}
|
||||||
|
|
||||||
|
return shortUrl.shortCode === shortCode && shortUrl.domain === domain;
|
||||||
|
};
|
||||||
|
|
||||||
|
const setPropFromActionOnMatchingShortUrl = (prop) => (state, { shortCode, domain, [prop]: propValue }) => assocPath(
|
||||||
[ 'shortUrls', 'data' ],
|
[ 'shortUrls', 'data' ],
|
||||||
state.shortUrls.data.map(
|
state.shortUrls.data.map(
|
||||||
(shortUrl) => shortUrl.shortCode === shortCode ? assoc(prop, propValue, shortUrl) : shortUrl
|
(shortUrl) => shortUrlMatches(shortUrl, shortCode, domain) ? assoc(prop, propValue, shortUrl) : shortUrl
|
||||||
),
|
),
|
||||||
state
|
state
|
||||||
);
|
);
|
||||||
|
@ -39,9 +47,9 @@ export default handleActions({
|
||||||
[LIST_SHORT_URLS_START]: (state) => ({ ...state, loading: true, error: false }),
|
[LIST_SHORT_URLS_START]: (state) => ({ ...state, loading: true, error: false }),
|
||||||
[LIST_SHORT_URLS]: (state, { shortUrls }) => ({ loading: false, error: false, shortUrls }),
|
[LIST_SHORT_URLS]: (state, { shortUrls }) => ({ loading: false, error: false, shortUrls }),
|
||||||
[LIST_SHORT_URLS_ERROR]: () => ({ loading: false, error: true, shortUrls: {} }),
|
[LIST_SHORT_URLS_ERROR]: () => ({ loading: false, error: true, shortUrls: {} }),
|
||||||
[SHORT_URL_DELETED]: (state, { shortCode }) => assocPath(
|
[SHORT_URL_DELETED]: (state, { shortCode, domain }) => assocPath(
|
||||||
[ 'shortUrls', 'data' ],
|
[ 'shortUrls', 'data' ],
|
||||||
reject(propEq('shortCode', shortCode), state.shortUrls.data),
|
reject((shortUrl) => shortUrlMatches(shortUrl, shortCode, domain), state.shortUrls.data),
|
||||||
state,
|
state,
|
||||||
),
|
),
|
||||||
[SHORT_URL_TAGS_EDITED]: setPropFromActionOnMatchingShortUrl('tags'),
|
[SHORT_URL_TAGS_EDITED]: setPropFromActionOnMatchingShortUrl('tags'),
|
||||||
|
|
|
@ -72,7 +72,7 @@ describe('shortUrlDeletionReducer', () => {
|
||||||
|
|
||||||
expect(dispatch).toHaveBeenCalledTimes(2);
|
expect(dispatch).toHaveBeenCalledTimes(2);
|
||||||
expect(dispatch).toHaveBeenNthCalledWith(1, { type: DELETE_SHORT_URL_START });
|
expect(dispatch).toHaveBeenNthCalledWith(1, { type: DELETE_SHORT_URL_START });
|
||||||
expect(dispatch).toHaveBeenNthCalledWith(2, { type: SHORT_URL_DELETED, shortCode });
|
expect(dispatch).toHaveBeenNthCalledWith(2, { type: SHORT_URL_DELETED, shortCode, domain });
|
||||||
|
|
||||||
expect(apiClientMock.deleteShortUrl).toHaveBeenCalledTimes(1);
|
expect(apiClientMock.deleteShortUrl).toHaveBeenCalledTimes(1);
|
||||||
expect(apiClientMock.deleteShortUrl).toHaveBeenCalledWith(shortCode, domain);
|
expect(apiClientMock.deleteShortUrl).toHaveBeenCalledWith(shortCode, domain);
|
||||||
|
|
|
@ -65,7 +65,7 @@ describe('shortUrlMetaReducer', () => {
|
||||||
expect(updateShortUrlMeta).toHaveBeenCalledWith(shortCode, domain, meta);
|
expect(updateShortUrlMeta).toHaveBeenCalledWith(shortCode, domain, meta);
|
||||||
expect(dispatch).toHaveBeenCalledTimes(2);
|
expect(dispatch).toHaveBeenCalledTimes(2);
|
||||||
expect(dispatch).toHaveBeenNthCalledWith(1, { type: EDIT_SHORT_URL_META_START });
|
expect(dispatch).toHaveBeenNthCalledWith(1, { type: EDIT_SHORT_URL_META_START });
|
||||||
expect(dispatch).toHaveBeenNthCalledWith(2, { type: SHORT_URL_META_EDITED, meta, shortCode });
|
expect(dispatch).toHaveBeenNthCalledWith(2, { type: SHORT_URL_META_EDITED, meta, shortCode, domain });
|
||||||
});
|
});
|
||||||
|
|
||||||
it('dispatches error on failure', async () => {
|
it('dispatches error on failure', async () => {
|
||||||
|
|
|
@ -73,7 +73,10 @@ describe('shortUrlTagsReducer', () => {
|
||||||
expect(updateShortUrlTags).toHaveBeenCalledWith(shortCode, domain, tags);
|
expect(updateShortUrlTags).toHaveBeenCalledWith(shortCode, domain, tags);
|
||||||
expect(dispatch).toHaveBeenCalledTimes(2);
|
expect(dispatch).toHaveBeenCalledTimes(2);
|
||||||
expect(dispatch).toHaveBeenNthCalledWith(1, { type: EDIT_SHORT_URL_TAGS_START });
|
expect(dispatch).toHaveBeenNthCalledWith(1, { type: EDIT_SHORT_URL_TAGS_START });
|
||||||
expect(dispatch).toHaveBeenNthCalledWith(2, { type: SHORT_URL_TAGS_EDITED, tags: normalizedTags, shortCode });
|
expect(dispatch).toHaveBeenNthCalledWith(
|
||||||
|
2,
|
||||||
|
{ type: SHORT_URL_TAGS_EDITED, tags: normalizedTags, shortCode, domain }
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('dispatches error on failure', async () => {
|
it('dispatches error on failure', async () => {
|
||||||
|
|
|
@ -38,15 +38,17 @@ describe('shortUrlsListReducer', () => {
|
||||||
shortUrls: {
|
shortUrls: {
|
||||||
data: [
|
data: [
|
||||||
{ shortCode, tags: [] },
|
{ shortCode, tags: [] },
|
||||||
|
{ shortCode, tags: [], domain: 'example.com' },
|
||||||
{ shortCode: 'foo', tags: [] },
|
{ shortCode: 'foo', tags: [] },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(reducer(state, { type: SHORT_URL_TAGS_EDITED, shortCode, tags })).toEqual({
|
expect(reducer(state, { type: SHORT_URL_TAGS_EDITED, shortCode, tags, domain: null })).toEqual({
|
||||||
shortUrls: {
|
shortUrls: {
|
||||||
data: [
|
data: [
|
||||||
{ shortCode, tags },
|
{ shortCode, tags },
|
||||||
|
{ shortCode, tags: [], domain: 'example.com' },
|
||||||
{ shortCode: 'foo', tags: [] },
|
{ shortCode: 'foo', tags: [] },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -55,6 +57,7 @@ describe('shortUrlsListReducer', () => {
|
||||||
|
|
||||||
it('Updates meta on matching URL on SHORT_URL_META_EDITED', () => {
|
it('Updates meta on matching URL on SHORT_URL_META_EDITED', () => {
|
||||||
const shortCode = 'abc123';
|
const shortCode = 'abc123';
|
||||||
|
const domain = 'example.com';
|
||||||
const meta = {
|
const meta = {
|
||||||
maxVisits: 5,
|
maxVisits: 5,
|
||||||
validSince: '2020-05-05',
|
validSince: '2020-05-05',
|
||||||
|
@ -62,16 +65,18 @@ describe('shortUrlsListReducer', () => {
|
||||||
const state = {
|
const state = {
|
||||||
shortUrls: {
|
shortUrls: {
|
||||||
data: [
|
data: [
|
||||||
{ shortCode, meta: { maxVisits: 10 } },
|
{ shortCode, meta: { maxVisits: 10 }, domain },
|
||||||
|
{ shortCode, meta: { maxVisits: 50 } },
|
||||||
{ shortCode: 'foo', meta: null },
|
{ shortCode: 'foo', meta: null },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(reducer(state, { type: SHORT_URL_META_EDITED, shortCode, meta })).toEqual({
|
expect(reducer(state, { type: SHORT_URL_META_EDITED, shortCode, meta, domain })).toEqual({
|
||||||
shortUrls: {
|
shortUrls: {
|
||||||
data: [
|
data: [
|
||||||
{ shortCode, meta },
|
{ shortCode, meta, domain: 'example.com' },
|
||||||
|
{ shortCode, meta: { maxVisits: 50 } },
|
||||||
{ shortCode: 'foo', meta: null },
|
{ shortCode: 'foo', meta: null },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -84,6 +89,7 @@ describe('shortUrlsListReducer', () => {
|
||||||
shortUrls: {
|
shortUrls: {
|
||||||
data: [
|
data: [
|
||||||
{ shortCode },
|
{ shortCode },
|
||||||
|
{ shortCode, domain: 'example.com' },
|
||||||
{ shortCode: 'foo' },
|
{ shortCode: 'foo' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@ -91,7 +97,7 @@ describe('shortUrlsListReducer', () => {
|
||||||
|
|
||||||
expect(reducer(state, { type: SHORT_URL_DELETED, shortCode })).toEqual({
|
expect(reducer(state, { type: SHORT_URL_DELETED, shortCode })).toEqual({
|
||||||
shortUrls: {
|
shortUrls: {
|
||||||
data: [{ shortCode: 'foo' }],
|
data: [{ shortCode, domain: 'example.com' }, { shortCode: 'foo' }],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue