From 3c9c0fe994e8548fc56711a955cd2b152bb76221 Mon Sep 17 00:00:00 2001 From: Alejandro Celaya Date: Fri, 5 Mar 2021 14:20:49 +0100 Subject: [PATCH] Added support for title field in short URL table --- src/short-urls/ShortUrlsList.scss | 2 +- src/short-urls/ShortUrlsTable.tsx | 35 +++++++++++++------ src/short-urls/data/index.ts | 1 + src/short-urls/helpers/ShortUrlsRow.scss | 4 --- src/short-urls/helpers/ShortUrlsRow.tsx | 9 +++-- .../reducers/shortUrlsListParams.ts | 1 + src/utils/helpers/features.ts | 7 ++++ test/short-urls/ShortUrlsTable.test.tsx | 35 ++++++++++++++----- 8 files changed, 68 insertions(+), 26 deletions(-) create mode 100644 src/utils/helpers/features.ts diff --git a/src/short-urls/ShortUrlsList.scss b/src/short-urls/ShortUrlsList.scss index f2a5edb2..5b1be099 100644 --- a/src/short-urls/ShortUrlsList.scss +++ b/src/short-urls/ShortUrlsList.scss @@ -1,3 +1,3 @@ .short-urls-list__header-icon { - margin-right: 5px; + margin-left: .4rem; } diff --git a/src/short-urls/ShortUrlsTable.tsx b/src/short-urls/ShortUrlsTable.tsx index 99e971a0..9bc0c9d6 100644 --- a/src/short-urls/ShortUrlsTable.tsx +++ b/src/short-urls/ShortUrlsTable.tsx @@ -2,6 +2,7 @@ import { FC, ReactNode } from 'react'; import { isEmpty } from 'ramda'; import classNames from 'classnames'; import { SelectedServer } from '../servers/data'; +import { titleIsSupported } from '../utils/helpers/features'; import { ShortUrlsList as ShortUrlsListState } from './reducers/shortUrlsList'; import { ShortUrlsRowProps } from './helpers/ShortUrlsRow'; import { OrderableFields } from './reducers/shortUrlsListParams'; @@ -25,10 +26,10 @@ export const ShortUrlsTable = (ShortUrlsRow: FC) => ({ className, }: ShortUrlsTableProps) => { const { error, loading, shortUrls } = shortUrlsList; - const orderableColumnsClasses = classNames('short-urls-table__header-cell', { - 'short-urls-table__header-cell--with-action': !!orderByColumn, - }); + const actionableFieldClasses = classNames({ 'short-urls-table__header-cell--with-action': !!orderByColumn }); + const orderableColumnsClasses = classNames('short-urls-table__header-cell', actionableFieldClasses); const tableClasses = classNames('table table-hover', className); + const supportsTitle = titleIsSupported(selectedServer); const renderShortUrls = () => { if (error) { @@ -62,20 +63,34 @@ export const ShortUrlsTable = (ShortUrlsRow: FC) => ({ - {renderOrderIcon?.('dateCreated')} Created at + {renderOrderIcon?.('dateCreated')} - {renderOrderIcon?.('shortCode')} Short URL + {renderOrderIcon?.('shortCode')} - - {renderOrderIcon?.('longUrl')} - Long URL - + {!supportsTitle && ( + + Long URL + {renderOrderIcon?.('longUrl')} + + ) || ( + + + Title + {renderOrderIcon?.('title')} + +   /   + + Long URL + {renderOrderIcon?.('longUrl')} + + + )} Tags - {renderOrderIcon?.('visits')} Visits + Visits{renderOrderIcon?.('visits')}   diff --git a/src/short-urls/data/index.ts b/src/short-urls/data/index.ts index 237c6b6a..44c280bf 100644 --- a/src/short-urls/data/index.ts +++ b/src/short-urls/data/index.ts @@ -23,6 +23,7 @@ export interface ShortUrl { meta: Required>; tags: string[]; domain: string | null; + title?: string | null; } export interface ShortUrlMeta { diff --git a/src/short-urls/helpers/ShortUrlsRow.scss b/src/short-urls/helpers/ShortUrlsRow.scss index 17ec51ac..a199b69b 100644 --- a/src/short-urls/helpers/ShortUrlsRow.scss +++ b/src/short-urls/helpers/ShortUrlsRow.scss @@ -44,10 +44,6 @@ position: relative; } -.short-urls-row__cell--big { - transform: scale(1.5); -} - .short-urls-row__copy-hint { @include vertical-align(translateX(10px)); diff --git a/src/short-urls/helpers/ShortUrlsRow.tsx b/src/short-urls/helpers/ShortUrlsRow.tsx index 5551938c..db40e670 100644 --- a/src/short-urls/helpers/ShortUrlsRow.tsx +++ b/src/short-urls/helpers/ShortUrlsRow.tsx @@ -64,9 +64,14 @@ const ShortUrlsRow = ( - - + + {shortUrl.title ?? shortUrl.longUrl} + {shortUrl.title && ( + + + + )} {renderTags(shortUrl.tags)} (selectedServer: SelectedServer): boolean => + isReachableServer(selectedServer) && versionMatch(selectedServer.version, versions); + +export const titleIsSupported = serverMatchesVersions({ minVersion: '2.6.0' }); diff --git a/test/short-urls/ShortUrlsTable.test.tsx b/test/short-urls/ShortUrlsTable.test.tsx index d486e4f0..74a736b3 100644 --- a/test/short-urls/ShortUrlsTable.test.tsx +++ b/test/short-urls/ShortUrlsTable.test.tsx @@ -2,23 +2,26 @@ import { shallow, ShallowWrapper } from 'enzyme'; import { Mock } from 'ts-mockery'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { ShortUrlsTable as shortUrlsTableCreator } from '../../src/short-urls/ShortUrlsTable'; -import { SORTABLE_FIELDS } from '../../src/short-urls/reducers/shortUrlsListParams'; +import { OrderableFields, SORTABLE_FIELDS } from '../../src/short-urls/reducers/shortUrlsListParams'; import { ShortUrlsList } from '../../src/short-urls/reducers/shortUrlsList'; +import { ReachableServer, SelectedServer } from '../../src/servers/data'; describe('', () => { let wrapper: ShallowWrapper; const shortUrlsList = Mock.all(); const orderByColumn = jest.fn(); const ShortUrlsRow = () => null; - const ShortUrlsTable = shortUrlsTableCreator(ShortUrlsRow); - beforeEach(() => { + const createWrapper = (server: SelectedServer = null) => { wrapper = shallow( - orderByColumn} />, + orderByColumn} />, ); - }); + return wrapper; + }; + + beforeEach(() => createWrapper()); afterEach(jest.resetAllMocks); afterEach(() => wrapper?.unmount()); @@ -42,13 +45,13 @@ describe('', () => { }); }); - it('should render 6 table header cells with conditional order by icon', () => { - const getThElementForSortableField = (sortableField: string) => wrapper.find('table') + it('should render table header cells with conditional order by icon', () => { + const getThElementForSortableField = (orderableField: string) => wrapper.find('table') .find('thead') .find('tr') .find('th') - .filterWhere((e) => e.text().includes(SORTABLE_FIELDS[sortableField as keyof typeof SORTABLE_FIELDS])); - const sortableFields = Object.keys(SORTABLE_FIELDS); + .filterWhere((e) => e.text().includes(SORTABLE_FIELDS[orderableField as OrderableFields])); + const sortableFields = Object.keys(SORTABLE_FIELDS).filter((sortableField) => sortableField !== 'title'); expect.assertions(sortableFields.length); sortableFields.forEach((sortableField) => { @@ -56,4 +59,18 @@ describe('', () => { expect(orderByColumn).toHaveBeenCalled(); }); }); + + it.each([ + [ '2.6.0' ], + [ '2.6.1' ], + [ '2.7.0' ], + [ '3.0.0' ], + ])('should render composed column when server supports title', (version) => { + const wrapper = createWrapper(Mock.of({ version })); + const composedColumn = wrapper.find('table').find('th').at(2); + const text = composedColumn.text(); + + expect(text).toContain('Title'); + expect(text).toContain('Long URL'); + }); });