mirror of
https://github.com/shlinkio/shlink-web-client.git
synced 2025-01-09 01:37:24 +03:00
Extracted short-url related services to its own service provider
This commit is contained in:
parent
cf1239cf6e
commit
4b1f5e9f4c
16 changed files with 94 additions and 121 deletions
|
@ -1,31 +1,18 @@
|
|||
import Bottle from 'bottlejs';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
import { connect as reduxConnect } from 'react-redux';
|
||||
import { assoc, pick } from 'ramda';
|
||||
import { pick } from 'ramda';
|
||||
import axios from 'axios';
|
||||
import App from '../App';
|
||||
import ScrollToTop from '../common/ScrollToTop';
|
||||
import MainHeader from '../common/MainHeader';
|
||||
import { resetSelectedServer } from '../servers/reducers/selectedServer';
|
||||
import Home from '../common/Home';
|
||||
import MenuLayout from '../common/MenuLayout';
|
||||
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 { ColorGenerator } from '../utils/ColorGenerator';
|
||||
import { Storage } from '../utils/Storage';
|
||||
import ShortUrlsRow from '../short-urls/helpers/ShortUrlsRow';
|
||||
import ShortUrlsRowMenu from '../short-urls/helpers/ShortUrlsRowMenu';
|
||||
import AsideMenu from '../common/AsideMenu';
|
||||
import CreateShortUrl from '../short-urls/CreateShortUrl';
|
||||
import { createShortUrl, resetCreateShortUrl } from '../short-urls/reducers/shortUrlCreation';
|
||||
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';
|
||||
import ColorGenerator from '../utils/ColorGenerator';
|
||||
import Storage from '../utils/Storage';
|
||||
import buildShlinkApiClient from '../api/ShlinkApiClientBuilder';
|
||||
import provideShortUrlsServices from '../short-urls/services/provideServices';
|
||||
import provideServersServices from '../servers/services/provideServices';
|
||||
import provideVisitsServices from '../visits/services/provideServices';
|
||||
import provideTagsServices from '../tags/services/provideServices';
|
||||
|
@ -54,7 +41,7 @@ bottle.serviceFactory('MainHeader', MainHeader, 'ServersDropdown');
|
|||
bottle.decorator('MainHeader', withRouter);
|
||||
|
||||
bottle.serviceFactory('Home', () => Home);
|
||||
bottle.decorator('Home', connect([ 'servers' ], { resetSelectedServer }));
|
||||
bottle.decorator('Home', connect([ 'servers' ], [ 'resetSelectedServer' ]));
|
||||
|
||||
bottle.serviceFactory(
|
||||
'MenuLayout',
|
||||
|
@ -77,49 +64,7 @@ bottle.service('ColorGenerator', ColorGenerator, 'Storage');
|
|||
bottle.constant('axios', axios);
|
||||
bottle.serviceFactory('buildShlinkApiClient', buildShlinkApiClient, 'axios');
|
||||
|
||||
bottle.serviceFactory('ShortUrls', ShortUrls, 'SearchBar', 'ShortUrlsList');
|
||||
bottle.decorator('ShortUrls', reduxConnect(
|
||||
(state) => assoc('shortUrlsList', state.shortUrlsList.shortUrls, state.shortUrlsList)
|
||||
));
|
||||
|
||||
bottle.serviceFactory('SearchBar', SearchBar, 'ColorGenerator');
|
||||
bottle.decorator('SearchBar', connect([ 'shortUrlsListParams' ], { listShortUrls }));
|
||||
|
||||
bottle.serviceFactory('ShortUrlsList', ShortUrlsList, 'ShortUrlsRow');
|
||||
bottle.decorator('ShortUrlsList', connect(
|
||||
[ 'selectedServer', 'shortUrlsListParams' ],
|
||||
[ 'listShortUrls', 'resetShortUrlParams' ]
|
||||
));
|
||||
|
||||
bottle.serviceFactory('ShortUrlsRow', ShortUrlsRow, 'ShortUrlsRowMenu', 'ColorGenerator');
|
||||
|
||||
bottle.serviceFactory('ShortUrlsRowMenu', ShortUrlsRowMenu, 'DeleteShortUrlModal', 'EditTagsModal');
|
||||
|
||||
bottle.serviceFactory('CreateShortUrl', CreateShortUrl, 'TagsSelector');
|
||||
bottle.decorator('CreateShortUrl', connect([ 'shortUrlCreationResult' ], {
|
||||
createShortUrl,
|
||||
resetCreateShortUrl,
|
||||
}));
|
||||
|
||||
bottle.serviceFactory('DeleteShortUrlModal', () => DeleteShortUrlModal);
|
||||
bottle.decorator('DeleteShortUrlModal', connect(
|
||||
[ 'shortUrlDeletion' ],
|
||||
{ deleteShortUrl, resetDeleteShortUrl, shortUrlDeleted }
|
||||
));
|
||||
|
||||
bottle.serviceFactory('EditTagsModal', EditTagsModal, 'TagsSelector');
|
||||
bottle.decorator('EditTagsModal', connect(
|
||||
[ 'shortUrlTags' ],
|
||||
[ 'editShortUrlTags', 'resetShortUrlsTags', 'shortUrlTagsEdited' ]
|
||||
));
|
||||
|
||||
bottle.serviceFactory('editShortUrlTags', editShortUrlTags, 'buildShlinkApiClient');
|
||||
bottle.serviceFactory('resetShortUrlsTags', () => resetShortUrlsTags);
|
||||
bottle.serviceFactory('shortUrlTagsEdited', () => shortUrlTagsEdited);
|
||||
|
||||
bottle.serviceFactory('listShortUrls', listShortUrls, 'buildShlinkApiClient');
|
||||
bottle.serviceFactory('resetShortUrlParams', () => resetShortUrlParams);
|
||||
|
||||
provideShortUrlsServices(bottle, connect);
|
||||
provideServersServices(bottle, connect, withRouter);
|
||||
provideTagsServices(bottle, connect);
|
||||
provideVisitsServices(bottle, connect);
|
||||
|
|
|
@ -23,8 +23,6 @@ export const resetSelectedServer = () => ({ type: RESET_SELECTED_SERVER });
|
|||
export const selectServer = (serversService) => (serverId) => (dispatch) => {
|
||||
dispatch(resetShortUrlParams());
|
||||
|
||||
console.log('Setting server');
|
||||
|
||||
const selectedServer = serversService.findServerById(serverId);
|
||||
|
||||
dispatch({
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
import { dissoc, head, keys, values } from 'ramda';
|
||||
import csvjson from 'csvjson';
|
||||
import serversService from './ServersService';
|
||||
|
||||
const saveCsv = (window, csv) => {
|
||||
const { navigator, document } = window;
|
||||
|
@ -26,7 +24,7 @@ const saveCsv = (window, csv) => {
|
|||
document.body.removeChild(link);
|
||||
};
|
||||
|
||||
export class ServersExporter {
|
||||
export default class ServersExporter {
|
||||
constructor(serversService, window, csvjson) {
|
||||
this.serversService = serversService;
|
||||
this.window = window;
|
||||
|
@ -49,7 +47,3 @@ export class ServersExporter {
|
|||
}
|
||||
};
|
||||
}
|
||||
|
||||
const serverExporter = new ServersExporter(serversService, global.window, csvjson);
|
||||
|
||||
export default serverExporter;
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
import csvjson from 'csvjson';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
export const serversImporterType = PropTypes.shape({
|
||||
importServersFromFile: PropTypes.func,
|
||||
});
|
||||
|
||||
export class ServersImporter {
|
||||
export default class ServersImporter {
|
||||
constructor(csvjson) {
|
||||
this.csvjson = csvjson;
|
||||
}
|
||||
|
@ -28,7 +27,3 @@ export class ServersImporter {
|
|||
});
|
||||
};
|
||||
}
|
||||
|
||||
const serversImporter = new ServersImporter(csvjson);
|
||||
|
||||
export default serversImporter;
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
import { assoc, dissoc, reduce } from 'ramda';
|
||||
import storage from '../../utils/Storage';
|
||||
|
||||
const SERVERS_STORAGE_KEY = 'servers';
|
||||
|
||||
export class ServersService {
|
||||
export default class ServersService {
|
||||
constructor(storage) {
|
||||
this.storage = storage;
|
||||
}
|
||||
|
@ -30,7 +29,3 @@ export class ServersService {
|
|||
dissoc(server.id, this.listServers())
|
||||
);
|
||||
}
|
||||
|
||||
const serversService = new ServersService(storage);
|
||||
|
||||
export default serversService;
|
||||
|
|
|
@ -6,9 +6,9 @@ import DeleteServerButton from '../DeleteServerButton';
|
|||
import ImportServersBtn from '../helpers/ImportServersBtn';
|
||||
import { resetSelectedServer, selectServer } from '../reducers/selectedServer';
|
||||
import { createServer, createServers, deleteServer, listServers } from '../reducers/server';
|
||||
import { ServersImporter } from './ServersImporter';
|
||||
import { ServersService } from './ServersService';
|
||||
import { ServersExporter } from './ServersExporter';
|
||||
import ServersImporter from './ServersImporter';
|
||||
import ServersService from './ServersService';
|
||||
import ServersExporter from './ServersExporter';
|
||||
|
||||
const provideServices = (bottle, connect, withRouter) => {
|
||||
// Components
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
import { curry } from 'ramda';
|
||||
import PropTypes from 'prop-types';
|
||||
import { buildShlinkApiClientWithAxios as buildShlinkApiClient } from '../../api/ShlinkApiClientBuilder';
|
||||
|
||||
/* eslint-disable padding-line-between-statements, newline-after-var */
|
||||
export const CREATE_SHORT_URL_START = 'shlink/createShortUrl/CREATE_SHORT_URL_START';
|
||||
|
@ -50,7 +48,7 @@ export default function reducer(state = defaultState, action) {
|
|||
}
|
||||
}
|
||||
|
||||
export const _createShortUrl = (buildShlinkApiClient, data) => async (dispatch, getState) => {
|
||||
export const createShortUrl = (buildShlinkApiClient) => (data) => async (dispatch, getState) => {
|
||||
dispatch({ type: CREATE_SHORT_URL_START });
|
||||
|
||||
const { selectedServer } = getState();
|
||||
|
@ -65,6 +63,4 @@ export const _createShortUrl = (buildShlinkApiClient, data) => async (dispatch,
|
|||
}
|
||||
};
|
||||
|
||||
export const createShortUrl = curry(_createShortUrl)(buildShlinkApiClient);
|
||||
|
||||
export const resetCreateShortUrl = () => ({ type: RESET_CREATE_SHORT_URL });
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
import { curry } from 'ramda';
|
||||
import PropTypes from 'prop-types';
|
||||
import { buildShlinkApiClientWithAxios as buildShlinkApiClient } from '../../api/ShlinkApiClientBuilder';
|
||||
|
||||
/* eslint-disable padding-line-between-statements, newline-after-var */
|
||||
const DELETE_SHORT_URL_START = 'shlink/deleteShortUrl/DELETE_SHORT_URL_START';
|
||||
|
@ -56,7 +54,7 @@ export default function reducer(state = defaultState, action) {
|
|||
}
|
||||
}
|
||||
|
||||
export const _deleteShortUrl = (buildShlinkApiClient, shortCode) => async (dispatch, getState) => {
|
||||
export const deleteShortUrl = (buildShlinkApiClient) => (shortCode) => async (dispatch, getState) => {
|
||||
dispatch({ type: DELETE_SHORT_URL_START });
|
||||
|
||||
const { selectedServer } = getState();
|
||||
|
@ -72,8 +70,6 @@ export const _deleteShortUrl = (buildShlinkApiClient, shortCode) => async (dispa
|
|||
}
|
||||
};
|
||||
|
||||
export const deleteShortUrl = curry(_deleteShortUrl)(buildShlinkApiClient);
|
||||
|
||||
export const resetDeleteShortUrl = () => ({ type: RESET_DELETE_SHORT_URL });
|
||||
|
||||
export const shortUrlDeleted = (shortCode) => ({ type: SHORT_URL_DELETED, shortCode });
|
||||
|
|
71
src/short-urls/services/provideServices.js
Normal file
71
src/short-urls/services/provideServices.js
Normal file
|
@ -0,0 +1,71 @@
|
|||
import { connect as reduxConnect } from 'react-redux';
|
||||
import { assoc } from 'ramda';
|
||||
import ShortUrls from '../ShortUrls';
|
||||
import SearchBar from '../SearchBar';
|
||||
import ShortUrlsList from '../ShortUrlsList';
|
||||
import ShortUrlsRow from '../helpers/ShortUrlsRow';
|
||||
import ShortUrlsRowMenu from '../helpers/ShortUrlsRowMenu';
|
||||
import CreateShortUrl from '../CreateShortUrl';
|
||||
import DeleteShortUrlModal from '../helpers/DeleteShortUrlModal';
|
||||
import EditTagsModal from '../helpers/EditTagsModal';
|
||||
import { listShortUrls } from '../reducers/shortUrlsList';
|
||||
import { createShortUrl, resetCreateShortUrl } from '../reducers/shortUrlCreation';
|
||||
import { deleteShortUrl, resetDeleteShortUrl, shortUrlDeleted } from '../reducers/shortUrlDeletion';
|
||||
import { editShortUrlTags, resetShortUrlsTags, shortUrlTagsEdited } from '../reducers/shortUrlTags';
|
||||
import { resetShortUrlParams } from '../reducers/shortUrlsListParams';
|
||||
|
||||
const provideServices = (bottle, connect) => {
|
||||
// Components
|
||||
bottle.serviceFactory('ShortUrls', ShortUrls, 'SearchBar', 'ShortUrlsList');
|
||||
bottle.decorator('ShortUrls', reduxConnect(
|
||||
(state) => assoc('shortUrlsList', state.shortUrlsList.shortUrls, state.shortUrlsList)
|
||||
));
|
||||
|
||||
bottle.serviceFactory('SearchBar', SearchBar, 'ColorGenerator');
|
||||
bottle.decorator('SearchBar', connect([ 'shortUrlsListParams' ], [ 'listShortUrls' ]));
|
||||
|
||||
bottle.serviceFactory('ShortUrlsList', ShortUrlsList, 'ShortUrlsRow');
|
||||
bottle.decorator('ShortUrlsList', connect(
|
||||
[ 'selectedServer', 'shortUrlsListParams' ],
|
||||
[ 'listShortUrls', 'resetShortUrlParams' ]
|
||||
));
|
||||
|
||||
bottle.serviceFactory('ShortUrlsRow', ShortUrlsRow, 'ShortUrlsRowMenu', 'ColorGenerator');
|
||||
|
||||
bottle.serviceFactory('ShortUrlsRowMenu', ShortUrlsRowMenu, 'DeleteShortUrlModal', 'EditTagsModal');
|
||||
|
||||
bottle.serviceFactory('CreateShortUrl', CreateShortUrl, 'TagsSelector');
|
||||
bottle.decorator(
|
||||
'CreateShortUrl',
|
||||
connect([ 'shortUrlCreationResult' ], [ 'createShortUrl', 'resetCreateShortUrl' ])
|
||||
);
|
||||
|
||||
bottle.serviceFactory('DeleteShortUrlModal', () => DeleteShortUrlModal);
|
||||
bottle.decorator('DeleteShortUrlModal', connect(
|
||||
[ 'shortUrlDeletion' ],
|
||||
[ 'deleteShortUrl', 'resetDeleteShortUrl', 'shortUrlDeleted' ]
|
||||
));
|
||||
|
||||
bottle.serviceFactory('EditTagsModal', EditTagsModal, 'TagsSelector');
|
||||
bottle.decorator('EditTagsModal', connect(
|
||||
[ 'shortUrlTags' ],
|
||||
[ 'editShortUrlTags', 'resetShortUrlsTags', 'shortUrlTagsEdited' ]
|
||||
));
|
||||
|
||||
// Actions
|
||||
bottle.serviceFactory('editShortUrlTags', editShortUrlTags, 'buildShlinkApiClient');
|
||||
bottle.serviceFactory('resetShortUrlsTags', () => resetShortUrlsTags);
|
||||
bottle.serviceFactory('shortUrlTagsEdited', () => shortUrlTagsEdited);
|
||||
|
||||
bottle.serviceFactory('listShortUrls', listShortUrls, 'buildShlinkApiClient');
|
||||
bottle.serviceFactory('resetShortUrlParams', () => resetShortUrlParams);
|
||||
|
||||
bottle.serviceFactory('createShortUrl', createShortUrl, 'buildShlinkApiClient');
|
||||
bottle.serviceFactory('resetCreateShortUrl', () => resetCreateShortUrl);
|
||||
|
||||
bottle.serviceFactory('deleteShortUrl', deleteShortUrl, 'buildShlinkApiClient');
|
||||
bottle.serviceFactory('resetDeleteShortUrl', () => resetDeleteShortUrl);
|
||||
bottle.serviceFactory('shortUrlDeleted', () => shortUrlDeleted);
|
||||
};
|
||||
|
||||
export default provideServices;
|
|
@ -1,6 +1,5 @@
|
|||
import { range } from 'ramda';
|
||||
import PropTypes from 'prop-types';
|
||||
import storage from './Storage';
|
||||
|
||||
const HEX_COLOR_LENGTH = 6;
|
||||
const { floor, random } = Math;
|
||||
|
@ -13,7 +12,7 @@ const buildRandomColor = () =>
|
|||
}`;
|
||||
const normalizeKey = (key) => key.toLowerCase().trim();
|
||||
|
||||
export class ColorGenerator {
|
||||
export default class ColorGenerator {
|
||||
constructor(storage) {
|
||||
this.storage = storage;
|
||||
this.colors = this.storage.get('colors') || {};
|
||||
|
@ -45,7 +44,3 @@ export const colorGeneratorType = PropTypes.shape({
|
|||
getColorForKey: PropTypes.func,
|
||||
setColorForKey: PropTypes.func,
|
||||
});
|
||||
|
||||
const colorGenerator = new ColorGenerator(storage);
|
||||
|
||||
export default colorGenerator;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
const PREFIX = 'shlink';
|
||||
const buildPath = (path) => `${PREFIX}.${path}`;
|
||||
|
||||
export class Storage {
|
||||
export default class Storage {
|
||||
constructor(localStorage) {
|
||||
this.localStorage = localStorage;
|
||||
}
|
||||
|
@ -14,15 +14,3 @@ export class Storage {
|
|||
|
||||
set = (key, value) => this.localStorage.setItem(buildPath(key), JSON.stringify(value));
|
||||
}
|
||||
|
||||
const browserStorage = global.localStorage || {
|
||||
getItem() {
|
||||
return '';
|
||||
},
|
||||
setItem() {
|
||||
return '';
|
||||
},
|
||||
};
|
||||
const storage = new Storage(browserStorage);
|
||||
|
||||
export default storage;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import sinon from 'sinon';
|
||||
import { ServersExporter } from '../../../src/servers/services/ServersExporter';
|
||||
import ServersExporter from '../../../src/servers/services/ServersExporter';
|
||||
|
||||
describe('ServersExporter', () => {
|
||||
const createLinkMock = () => ({
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import sinon from 'sinon';
|
||||
import { ServersImporter } from '../../../src/servers/services/ServersImporter';
|
||||
import ServersImporter from '../../../src/servers/services/ServersImporter';
|
||||
|
||||
describe('ServersImporter', () => {
|
||||
const servers = [{ name: 'foo' }, { name: 'bar' }];
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import sinon from 'sinon';
|
||||
import { last } from 'ramda';
|
||||
import { ServersService } from '../../../src/servers/services/ServersService';
|
||||
import ServersService from '../../../src/servers/services/ServersService';
|
||||
|
||||
describe('ServersService', () => {
|
||||
const servers = {
|
||||
|
|
|
@ -4,7 +4,7 @@ import reducer, {
|
|||
CREATE_SHORT_URL_ERROR,
|
||||
CREATE_SHORT_URL,
|
||||
RESET_CREATE_SHORT_URL,
|
||||
_createShortUrl,
|
||||
createShortUrl,
|
||||
resetCreateShortUrl,
|
||||
} from '../../../src/short-urls/reducers/shortUrlCreation';
|
||||
|
||||
|
@ -62,7 +62,7 @@ describe('shortUrlCreationReducer', () => {
|
|||
const expectedDispatchCalls = 2;
|
||||
const result = 'foo';
|
||||
const apiClientMock = createApiClientMock(Promise.resolve(result));
|
||||
const dispatchable = _createShortUrl(() => apiClientMock, {});
|
||||
const dispatchable = createShortUrl(() => apiClientMock)({});
|
||||
|
||||
await dispatchable(dispatch, getState);
|
||||
|
||||
|
@ -77,7 +77,7 @@ describe('shortUrlCreationReducer', () => {
|
|||
const expectedDispatchCalls = 2;
|
||||
const error = 'Error';
|
||||
const apiClientMock = createApiClientMock(Promise.reject(error));
|
||||
const dispatchable = _createShortUrl(() => apiClientMock, {});
|
||||
const dispatchable = createShortUrl(() => apiClientMock)({});
|
||||
|
||||
try {
|
||||
await dispatchable(dispatch, getState);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import * as sinon from 'sinon';
|
||||
import { ColorGenerator } from '../../src/utils/ColorGenerator';
|
||||
import ColorGenerator from '../../src/utils/ColorGenerator';
|
||||
|
||||
describe('ColorGenerator', () => {
|
||||
let colorGenerator;
|
||||
|
|
Loading…
Reference in a new issue