From 992b22fd2415e3cfc1e29443bfa3a56c61e54adb Mon Sep 17 00:00:00 2001 From: Alejandro Celaya Date: Fri, 21 Apr 2023 09:36:51 +0200 Subject: [PATCH] Refactor short URL export so that it is compatible with what Shlink expects --- src/common/services/ReportExporter.ts | 1 - src/short-urls/data/index.ts | 2 ++ src/short-urls/helpers/ExportShortUrlsBtn.tsx | 28 ++++++++++++------- .../helpers/ExportShortUrlsBtn.test.tsx | 19 +++++++++++++ 4 files changed, 39 insertions(+), 11 deletions(-) diff --git a/src/common/services/ReportExporter.ts b/src/common/services/ReportExporter.ts index 2ea0cd11..d23b3bfe 100644 --- a/src/common/services/ReportExporter.ts +++ b/src/common/services/ReportExporter.ts @@ -24,7 +24,6 @@ export class ReportExporter { private readonly exportCsv = (filename: string, rows: object[]) => { const csv = this.jsonToCsv(rows); - saveCsv(this.window, csv, filename); }; } diff --git a/src/short-urls/data/index.ts b/src/short-urls/data/index.ts index 7d37e935..28219583 100644 --- a/src/short-urls/data/index.ts +++ b/src/short-urls/data/index.ts @@ -79,6 +79,8 @@ export interface ExportableShortUrl { createdAt: string; title: string; shortUrl: string; + domain?: string; + shortCode: string; longUrl: string; tags: string; visits: number; diff --git a/src/short-urls/helpers/ExportShortUrlsBtn.tsx b/src/short-urls/helpers/ExportShortUrlsBtn.tsx index 88f502e7..7fcc01ee 100644 --- a/src/short-urls/helpers/ExportShortUrlsBtn.tsx +++ b/src/short-urls/helpers/ExportShortUrlsBtn.tsx @@ -1,4 +1,5 @@ import type { FC } from 'react'; +import { useCallback } from 'react'; import type { ShlinkApiClientBuilder } from '../../api/services/ShlinkApiClientBuilder'; import type { ReportExporter } from '../../common/services/ReportExporter'; import type { SelectedServer } from '../../servers/data'; @@ -24,7 +25,7 @@ export const ExportShortUrlsBtn = ( ): FC => ({ amount = 0, selectedServer }) => { const [{ tags, search, startDate, endDate, orderBy, tagsMode }] = useShortUrlsQuery(); const [loading,, startLoading, stopLoading] = useToggle(); - const exportAllUrls = async () => { + const exportAllUrls = useCallback(async () => { if (!isServerWithId(selectedServer)) { return; } @@ -47,16 +48,23 @@ export const ExportShortUrlsBtn = ( startLoading(); const shortUrls = await loadAllUrls(); - exportShortUrls(shortUrls.map((shortUrl) => ({ - createdAt: shortUrl.dateCreated, - shortUrl: shortUrl.shortUrl, - longUrl: shortUrl.longUrl, - title: shortUrl.title ?? '', - tags: shortUrl.tags.join(','), - visits: shortUrl?.visitsSummary?.total ?? shortUrl.visitsCount, - }))); + exportShortUrls(shortUrls.map((shortUrl) => { + const { hostname: domain, pathname } = new URL(shortUrl.shortUrl); + const shortCode = pathname.substring(1); // Remove trailing slash + + return { + createdAt: shortUrl.dateCreated, + domain, + shortCode, + shortUrl: shortUrl.shortUrl, + longUrl: shortUrl.longUrl, + title: shortUrl.title ?? '', + tags: shortUrl.tags.join('|'), + visits: shortUrl?.visitsSummary?.total ?? shortUrl.visitsCount, + }; + })); stopLoading(); - }; + }, [selectedServer]); return ; }; diff --git a/test/short-urls/helpers/ExportShortUrlsBtn.test.tsx b/test/short-urls/helpers/ExportShortUrlsBtn.test.tsx index 0724215b..2e8fb718 100644 --- a/test/short-urls/helpers/ExportShortUrlsBtn.test.tsx +++ b/test/short-urls/helpers/ExportShortUrlsBtn.test.tsx @@ -3,6 +3,7 @@ import { fromPartial } from '@total-typescript/shoehorn'; import { MemoryRouter } from 'react-router-dom'; import type { ReportExporter } from '../../../src/common/services/ReportExporter'; import type { NotFoundServer, SelectedServer } from '../../../src/servers/data'; +import type { ShortUrl } from '../../../src/short-urls/data'; import { ExportShortUrlsBtn as createExportShortUrlsBtn } from '../../../src/short-urls/helpers/ExportShortUrlsBtn'; import { renderWithEvents } from '../../__helpers__/setUpTest'; @@ -56,4 +57,22 @@ describe('', () => { expect(listShortUrls).toHaveBeenCalledTimes(expectedPageLoads); expect(exportShortUrls).toHaveBeenCalled(); }); + + it('maps short URLs for exporting', async () => { + listShortUrls.mockResolvedValue({ + data: [fromPartial({ + shortUrl: 'https://s.test/short-code', + tags: [], + })], + }); + const { user } = setUp(undefined, fromPartial({ id: '123' })); + + await user.click(screen.getByRole('button')); + + expect(exportShortUrls).toHaveBeenCalledWith([expect.objectContaining({ + shortUrl: 'https://s.test/short-code', + domain: 's.test', + shortCode: 'short-code', + })]); + }); });