mirror of
https://github.com/shlinkio/shlink-web-client.git
synced 2025-01-10 18:27:25 +03:00
Created single reducer to handle settings
This commit is contained in:
parent
3953e98a77
commit
bbc47b387e
11 changed files with 40 additions and 32 deletions
|
@ -14,7 +14,7 @@ import tagsListReducer from '../tags/reducers/tagsList';
|
|||
import tagDeleteReducer from '../tags/reducers/tagDelete';
|
||||
import tagEditReducer from '../tags/reducers/tagEdit';
|
||||
import mercureInfoReducer from '../mercure/reducers/mercureInfo';
|
||||
import realTimeUpdatesReducer from '../settings/reducers/realTimeUpdates';
|
||||
import settingsReducer from '../settings/reducers/settings';
|
||||
|
||||
export default combineReducers({
|
||||
servers: serversReducer,
|
||||
|
@ -32,5 +32,5 @@ export default combineReducers({
|
|||
tagDelete: tagDeleteReducer,
|
||||
tagEdit: tagEditReducer,
|
||||
mercureInfo: mercureInfoReducer,
|
||||
realTimeUpdates: realTimeUpdatesReducer,
|
||||
settings: settingsReducer,
|
||||
});
|
||||
|
|
|
@ -4,14 +4,14 @@ import PropTypes from 'prop-types';
|
|||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { faInfoCircle } from '@fortawesome/free-solid-svg-icons';
|
||||
import Checkbox from '../utils/Checkbox';
|
||||
import { RealTimeUpdatesType } from './reducers/realTimeUpdates';
|
||||
import { SettingsType } from './reducers/settings';
|
||||
|
||||
const propTypes = {
|
||||
realTimeUpdates: RealTimeUpdatesType,
|
||||
settings: SettingsType,
|
||||
setRealTimeUpdates: PropTypes.func,
|
||||
};
|
||||
|
||||
const RealTimeUpdates = ({ realTimeUpdates, setRealTimeUpdates }) => (
|
||||
const RealTimeUpdates = ({ settings: { realTimeUpdates }, setRealTimeUpdates }) => (
|
||||
<Card>
|
||||
<CardHeader>Real-time updates</CardHeader>
|
||||
<CardBody>
|
||||
|
|
|
@ -3,16 +3,20 @@ import PropTypes from 'prop-types';
|
|||
|
||||
export const LOAD_REAL_TIME_UPDATES = 'shlink/realTimeUpdates/LOAD_REAL_TIME_UPDATES';
|
||||
|
||||
export const RealTimeUpdatesType = PropTypes.shape({
|
||||
enabled: PropTypes.bool.isRequired,
|
||||
export const SettingsType = PropTypes.shape({
|
||||
realTimeUpdates: PropTypes.shape({
|
||||
enabled: PropTypes.bool.isRequired,
|
||||
}),
|
||||
});
|
||||
|
||||
const initialState = {
|
||||
enabled: true,
|
||||
realTimeUpdates: {
|
||||
enabled: true,
|
||||
},
|
||||
};
|
||||
|
||||
export default handleActions({
|
||||
[LOAD_REAL_TIME_UPDATES]: (state, { enabled }) => ({ ...state, enabled }),
|
||||
[LOAD_REAL_TIME_UPDATES]: (state, { realTimeUpdates }) => ({ ...state, realTimeUpdates }),
|
||||
}, initialState);
|
||||
|
||||
export const setRealTimeUpdates = ({ updateSettings }, loadRealTimeUpdatesAction) => (enabled) => {
|
||||
|
@ -23,10 +27,9 @@ export const setRealTimeUpdates = ({ updateSettings }, loadRealTimeUpdatesAction
|
|||
|
||||
export const loadRealTimeUpdates = ({ loadSettings }) => () => {
|
||||
const { realTimeUpdates = {} } = loadSettings();
|
||||
const { enabled = true } = realTimeUpdates;
|
||||
|
||||
return {
|
||||
type: LOAD_REAL_TIME_UPDATES,
|
||||
enabled,
|
||||
realTimeUpdates,
|
||||
};
|
||||
};
|
|
@ -1,6 +1,6 @@
|
|||
import RealTimeUpdates from '../RealTimeUpdates';
|
||||
import Settings from '../Settings';
|
||||
import { loadRealTimeUpdates, setRealTimeUpdates } from '../reducers/realTimeUpdates';
|
||||
import { loadRealTimeUpdates, setRealTimeUpdates } from '../reducers/settings';
|
||||
import SettingsService from './SettingsService';
|
||||
|
||||
const provideServices = (bottle, connect) => {
|
||||
|
@ -8,7 +8,7 @@ const provideServices = (bottle, connect) => {
|
|||
bottle.serviceFactory('Settings', Settings, 'RealTimeUpdates');
|
||||
|
||||
bottle.serviceFactory('RealTimeUpdates', () => RealTimeUpdates);
|
||||
bottle.decorator('RealTimeUpdates', connect([ 'realTimeUpdates' ], [ 'setRealTimeUpdates' ]));
|
||||
bottle.decorator('RealTimeUpdates', connect([ 'settings' ], [ 'setRealTimeUpdates' ]));
|
||||
|
||||
// Services
|
||||
bottle.service('SettingsService', SettingsService, 'Storage');
|
||||
|
|
|
@ -9,7 +9,7 @@ import SortingDropdown from '../utils/SortingDropdown';
|
|||
import { determineOrderDir } from '../utils/utils';
|
||||
import { MercureInfoType } from '../mercure/reducers/mercureInfo';
|
||||
import { bindToMercureTopic } from '../mercure/helpers';
|
||||
import { RealTimeUpdatesType } from '../settings/reducers/realTimeUpdates';
|
||||
import { SettingsType } from '../settings/reducers/settings';
|
||||
import { shortUrlType } from './reducers/shortUrlsList';
|
||||
import { shortUrlsListParamsType } from './reducers/shortUrlsListParams';
|
||||
import './ShortUrlsList.scss';
|
||||
|
@ -34,7 +34,7 @@ const propTypes = {
|
|||
createNewVisit: PropTypes.func,
|
||||
loadMercureInfo: PropTypes.func,
|
||||
mercureInfo: MercureInfoType,
|
||||
realTimeUpdates: RealTimeUpdatesType,
|
||||
settings: SettingsType,
|
||||
};
|
||||
|
||||
// FIXME Replace with typescript: (ShortUrlsRow component)
|
||||
|
@ -52,7 +52,7 @@ const ShortUrlsList = (ShortUrlsRow) => {
|
|||
createNewVisit,
|
||||
loadMercureInfo,
|
||||
mercureInfo,
|
||||
realTimeUpdates,
|
||||
settings: { realTimeUpdates },
|
||||
}) => {
|
||||
const { orderBy } = shortUrlsListParams;
|
||||
const [ order, setOrder ] = useState({
|
||||
|
|
|
@ -31,7 +31,7 @@ const provideServices = (bottle, connect) => {
|
|||
|
||||
bottle.serviceFactory('ShortUrlsList', ShortUrlsList, 'ShortUrlsRow');
|
||||
bottle.decorator('ShortUrlsList', connect(
|
||||
[ 'selectedServer', 'shortUrlsListParams', 'mercureInfo', 'realTimeUpdates' ],
|
||||
[ 'selectedServer', 'shortUrlsListParams', 'mercureInfo', 'settings' ],
|
||||
[ 'listShortUrls', 'resetShortUrlParams', 'createNewVisit', 'loadMercureInfo' ]
|
||||
));
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ import { formatDate } from '../utils/helpers/date';
|
|||
import { useToggle } from '../utils/helpers/hooks';
|
||||
import { MercureInfoType } from '../mercure/reducers/mercureInfo';
|
||||
import { bindToMercureTopic } from '../mercure/helpers';
|
||||
import { RealTimeUpdatesType } from '../settings/reducers/realTimeUpdates';
|
||||
import { SettingsType } from '../settings/reducers/settings';
|
||||
import SortableBarGraph from './SortableBarGraph';
|
||||
import { shortUrlVisitsType } from './reducers/shortUrlVisits';
|
||||
import VisitsHeader from './VisitsHeader';
|
||||
|
@ -39,7 +39,7 @@ const propTypes = {
|
|||
createNewVisit: PropTypes.func,
|
||||
loadMercureInfo: PropTypes.func,
|
||||
mercureInfo: MercureInfoType,
|
||||
realTimeUpdates: RealTimeUpdatesType,
|
||||
settings: SettingsType,
|
||||
};
|
||||
|
||||
const highlightedVisitsToStats = (highlightedVisits, prop) => highlightedVisits.reduce((acc, highlightedVisit) => {
|
||||
|
@ -68,7 +68,7 @@ const ShortUrlVisits = ({ processStatsFromVisits, normalizeVisits }, OpenMapModa
|
|||
createNewVisit,
|
||||
loadMercureInfo,
|
||||
mercureInfo,
|
||||
realTimeUpdates,
|
||||
settings: { realTimeUpdates },
|
||||
}) => {
|
||||
const [ startDate, setStartDate ] = useState(undefined);
|
||||
const [ endDate, setEndDate ] = useState(undefined);
|
||||
|
|
|
@ -11,7 +11,7 @@ const provideServices = (bottle, connect) => {
|
|||
bottle.serviceFactory('MapModal', () => MapModal);
|
||||
bottle.serviceFactory('ShortUrlVisits', ShortUrlVisits, 'VisitsParser', 'OpenMapModalBtn');
|
||||
bottle.decorator('ShortUrlVisits', connect(
|
||||
[ 'shortUrlVisits', 'shortUrlDetail', 'mercureInfo', 'realTimeUpdates' ],
|
||||
[ 'shortUrlVisits', 'shortUrlDetail', 'mercureInfo', 'settings' ],
|
||||
[ 'getShortUrlVisits', 'getShortUrlDetail', 'cancelGetShortUrlVisits', 'createNewVisit', 'loadMercureInfo' ]
|
||||
));
|
||||
|
||||
|
|
|
@ -2,34 +2,35 @@ import reducer, {
|
|||
LOAD_REAL_TIME_UPDATES,
|
||||
loadRealTimeUpdates,
|
||||
setRealTimeUpdates,
|
||||
} from '../../../src/settings/reducers/realTimeUpdates';
|
||||
} from '../../../src/settings/reducers/settings';
|
||||
|
||||
describe('realTimeUpdatesReducer', () => {
|
||||
describe('settingsReducer', () => {
|
||||
const SettingsServiceMock = {
|
||||
updateSettings: jest.fn(),
|
||||
loadSettings: jest.fn(),
|
||||
};
|
||||
const realTimeUpdates = { enabled: true };
|
||||
|
||||
afterEach(jest.clearAllMocks);
|
||||
|
||||
describe('reducer', () => {
|
||||
it('returns realTimeUpdates when action is LOAD_REAL_TIME_UPDATES', () => {
|
||||
expect(reducer({}, { type: LOAD_REAL_TIME_UPDATES, enabled: true })).toEqual({ enabled: true });
|
||||
expect(reducer({}, { type: LOAD_REAL_TIME_UPDATES, realTimeUpdates })).toEqual({ realTimeUpdates });
|
||||
});
|
||||
});
|
||||
|
||||
describe('loadRealTimeUpdates', () => {
|
||||
it.each([
|
||||
[{}, true ],
|
||||
[{ realTimeUpdates: {} }, true ],
|
||||
[{ realTimeUpdates: { enabled: true } }, true ],
|
||||
[{ realTimeUpdates: { enabled: false } }, false ],
|
||||
])('loads settings and returns LOAD_REAL_TIME_UPDATES action', (loadedSettings, expectedEnabled) => {
|
||||
SettingsServiceMock.loadSettings.mockReturnValue(loadedSettings);
|
||||
it.each([[ true ], [ false ]])('loads settings and returns LOAD_REAL_TIME_UPDATES action', (enabled) => {
|
||||
const realTimeUpdates = { enabled };
|
||||
|
||||
SettingsServiceMock.loadSettings.mockReturnValue({ realTimeUpdates });
|
||||
|
||||
const result = loadRealTimeUpdates(SettingsServiceMock)();
|
||||
|
||||
expect(result).toEqual({ type: LOAD_REAL_TIME_UPDATES, enabled: expectedEnabled });
|
||||
expect(result).toEqual({
|
||||
type: LOAD_REAL_TIME_UPDATES,
|
||||
realTimeUpdates,
|
||||
});
|
||||
expect(SettingsServiceMock.loadSettings).toHaveBeenCalled();
|
||||
});
|
||||
});
|
|
@ -9,6 +9,7 @@ describe('<ShortUrlsList />', () => {
|
|||
const ShortUrlsRow = () => '';
|
||||
const listShortUrlsMock = jest.fn();
|
||||
const resetShortUrlParamsMock = jest.fn();
|
||||
const realTimeUpdates = { enabled: true };
|
||||
|
||||
const ShortUrlsList = shortUrlsListCreator(ShortUrlsRow);
|
||||
|
||||
|
@ -37,6 +38,7 @@ describe('<ShortUrlsList />', () => {
|
|||
]
|
||||
}
|
||||
mercureInfo={{ loading: true }}
|
||||
settings={{ realTimeUpdates }}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
|
|
@ -21,6 +21,7 @@ describe('<ShortUrlVisits />', () => {
|
|||
const history = {
|
||||
goBack: jest.fn(),
|
||||
};
|
||||
const realTimeUpdates = { enabled: true };
|
||||
|
||||
const createComponent = (shortUrlVisits) => {
|
||||
const ShortUrlVisits = createShortUrlVisits({ processStatsFromVisits, normalizeVisits: identity }, () => '');
|
||||
|
@ -36,6 +37,7 @@ describe('<ShortUrlVisits />', () => {
|
|||
shortUrlDetail={{}}
|
||||
cancelGetShortUrlVisits={identity}
|
||||
matchMedia={() => ({ matches: false })}
|
||||
settings={{ realTimeUpdates }}
|
||||
/>
|
||||
);
|
||||
|
||||
|
|
Loading…
Reference in a new issue