mirror of
https://github.com/shlinkio/shlink-web-client.git
synced 2024-12-23 17:40:23 +03:00
Merge pull request #300 from acelaya-forks/feature/default-ordering
Feature/default ordering
This commit is contained in:
commit
89e3114ef3
5 changed files with 25 additions and 18 deletions
|
@ -18,6 +18,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
|
|
||||||
#### Changed
|
#### Changed
|
||||||
|
|
||||||
|
* [#150](https://github.com/shlinkio/shlink-web-client/issues/150) The list of short URLs is now ordered by the creation date, showing newest results first.
|
||||||
* [#40](https://github.com/shlinkio/shlink-web-client/issues/40) Migrated project to TypeScript.
|
* [#40](https://github.com/shlinkio/shlink-web-client/issues/40) Migrated project to TypeScript.
|
||||||
|
|
||||||
#### Deprecated
|
#### Deprecated
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { faCaretDown as caretDownIcon, faCaretUp as caretUpIcon } from '@fortawesome/free-solid-svg-icons';
|
import { faCaretDown as caretDownIcon, faCaretUp as caretUpIcon } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
import { head, isEmpty, keys, values } from 'ramda';
|
import { head, isEmpty, keys, values } from 'ramda';
|
||||||
import React, { useState, useEffect, FC } from 'react';
|
import React, { FC, useEffect, useState } from 'react';
|
||||||
import qs from 'qs';
|
import qs from 'qs';
|
||||||
import { RouteComponentProps } from 'react-router';
|
import { RouteComponentProps } from 'react-router';
|
||||||
import SortingDropdown from '../utils/SortingDropdown';
|
import SortingDropdown from '../utils/SortingDropdown';
|
||||||
|
@ -11,17 +11,9 @@ import { boundToMercureHub } from '../mercure/helpers/boundToMercureHub';
|
||||||
import { ShortUrlsList as ShortUrlsListState } from './reducers/shortUrlsList';
|
import { ShortUrlsList as ShortUrlsListState } from './reducers/shortUrlsList';
|
||||||
import { ShortUrlsRowProps } from './helpers/ShortUrlsRow';
|
import { ShortUrlsRowProps } from './helpers/ShortUrlsRow';
|
||||||
import { ShortUrl } from './data';
|
import { ShortUrl } from './data';
|
||||||
import { ShortUrlsListParams } from './reducers/shortUrlsListParams';
|
import { OrderableFields, ShortUrlsListParams, SORTABLE_FIELDS } from './reducers/shortUrlsListParams';
|
||||||
import './ShortUrlsList.scss';
|
import './ShortUrlsList.scss';
|
||||||
|
|
||||||
export const SORTABLE_FIELDS = {
|
|
||||||
dateCreated: 'Created at',
|
|
||||||
shortCode: 'Short URL',
|
|
||||||
longUrl: 'Long URL',
|
|
||||||
visits: 'Visits',
|
|
||||||
};
|
|
||||||
type OrderableFields = keyof typeof SORTABLE_FIELDS;
|
|
||||||
|
|
||||||
interface RouteParams {
|
interface RouteParams {
|
||||||
page: string;
|
page: string;
|
||||||
serverId: string;
|
serverId: string;
|
||||||
|
|
|
@ -4,16 +4,28 @@ import { LIST_SHORT_URLS, ListShortUrlsAction } from './shortUrlsList';
|
||||||
|
|
||||||
export const RESET_SHORT_URL_PARAMS = 'shlink/shortUrlsListParams/RESET_SHORT_URL_PARAMS';
|
export const RESET_SHORT_URL_PARAMS = 'shlink/shortUrlsListParams/RESET_SHORT_URL_PARAMS';
|
||||||
|
|
||||||
|
export const SORTABLE_FIELDS = {
|
||||||
|
dateCreated: 'Created at',
|
||||||
|
shortCode: 'Short URL',
|
||||||
|
longUrl: 'Long URL',
|
||||||
|
visits: 'Visits',
|
||||||
|
};
|
||||||
|
|
||||||
|
export type OrderableFields = keyof typeof SORTABLE_FIELDS;
|
||||||
|
|
||||||
export interface ShortUrlsListParams {
|
export interface ShortUrlsListParams {
|
||||||
page?: string;
|
page?: string;
|
||||||
tags?: string[];
|
tags?: string[];
|
||||||
searchTerm?: string;
|
searchTerm?: string;
|
||||||
startDate?: string;
|
startDate?: string;
|
||||||
endDate?: string;
|
endDate?: string;
|
||||||
orderBy?: Record<string, OrderDir>;
|
orderBy?: Partial<Record<OrderableFields, OrderDir>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const initialState: ShortUrlsListParams = { page: '1' };
|
const initialState: ShortUrlsListParams = {
|
||||||
|
page: '1',
|
||||||
|
orderBy: { dateCreated: 'DESC' },
|
||||||
|
};
|
||||||
|
|
||||||
export default buildReducer<ShortUrlsListParams, ListShortUrlsAction>({
|
export default buildReducer<ShortUrlsListParams, ListShortUrlsAction>({
|
||||||
[LIST_SHORT_URLS]: (state, { params }) => ({ ...state, ...params }),
|
[LIST_SHORT_URLS]: (state, { params }) => ({ ...state, ...params }),
|
||||||
|
|
|
@ -3,9 +3,10 @@ import { shallow, ShallowWrapper } from 'enzyme';
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
import { faCaretDown as caretDownIcon, faCaretUp as caretUpIcon } from '@fortawesome/free-solid-svg-icons';
|
import { faCaretDown as caretDownIcon, faCaretUp as caretUpIcon } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { Mock } from 'ts-mockery';
|
import { Mock } from 'ts-mockery';
|
||||||
import shortUrlsListCreator, { ShortUrlsListProps, SORTABLE_FIELDS } from '../../src/short-urls/ShortUrlsList';
|
import shortUrlsListCreator, { ShortUrlsListProps } from '../../src/short-urls/ShortUrlsList';
|
||||||
import { ShortUrl } from '../../src/short-urls/data';
|
import { ShortUrl } from '../../src/short-urls/data';
|
||||||
import { MercureBoundProps } from '../../src/mercure/helpers/boundToMercureHub';
|
import { MercureBoundProps } from '../../src/mercure/helpers/boundToMercureHub';
|
||||||
|
import { SORTABLE_FIELDS } from '../../src/short-urls/reducers/shortUrlsListParams';
|
||||||
|
|
||||||
describe('<ShortUrlsList />', () => {
|
describe('<ShortUrlsList />', () => {
|
||||||
let wrapper: ShallowWrapper;
|
let wrapper: ShallowWrapper;
|
||||||
|
|
|
@ -1,22 +1,23 @@
|
||||||
import reducer, {
|
import reducer, {
|
||||||
RESET_SHORT_URL_PARAMS,
|
RESET_SHORT_URL_PARAMS,
|
||||||
resetShortUrlParams,
|
resetShortUrlParams,
|
||||||
ShortUrlsListParams,
|
|
||||||
} from '../../../src/short-urls/reducers/shortUrlsListParams';
|
} from '../../../src/short-urls/reducers/shortUrlsListParams';
|
||||||
import { LIST_SHORT_URLS } from '../../../src/short-urls/reducers/shortUrlsList';
|
import { LIST_SHORT_URLS } from '../../../src/short-urls/reducers/shortUrlsList';
|
||||||
|
|
||||||
describe('shortUrlsListParamsReducer', () => {
|
describe('shortUrlsListParamsReducer', () => {
|
||||||
describe('reducer', () => {
|
describe('reducer', () => {
|
||||||
const defaultState: ShortUrlsListParams = { page: '1' };
|
|
||||||
|
|
||||||
it('returns params when action is LIST_SHORT_URLS', () =>
|
it('returns params when action is LIST_SHORT_URLS', () =>
|
||||||
expect(reducer(undefined, { type: LIST_SHORT_URLS, params: { searchTerm: 'foo', page: '2' } })).toEqual({
|
expect(reducer(undefined, { type: LIST_SHORT_URLS, params: { searchTerm: 'foo', page: '2' } } as any)).toEqual({
|
||||||
page: '2',
|
page: '2',
|
||||||
searchTerm: 'foo',
|
searchTerm: 'foo',
|
||||||
|
orderBy: { dateCreated: 'DESC' },
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('returns default value when action is RESET_SHORT_URL_PARAMS', () =>
|
it('returns default value when action is RESET_SHORT_URL_PARAMS', () =>
|
||||||
expect(reducer(undefined, { type: RESET_SHORT_URL_PARAMS, params: defaultState })).toEqual(defaultState));
|
expect(reducer(undefined, { type: RESET_SHORT_URL_PARAMS } as any)).toEqual({
|
||||||
|
page: '1',
|
||||||
|
orderBy: { dateCreated: 'DESC' },
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('resetShortUrlParams', () => {
|
describe('resetShortUrlParams', () => {
|
||||||
|
|
Loading…
Reference in a new issue