From 992b22fd2415e3cfc1e29443bfa3a56c61e54adb Mon Sep 17 00:00:00 2001 From: Alejandro Celaya Date: Fri, 21 Apr 2023 09:36:51 +0200 Subject: [PATCH 1/3] 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', + })]); + }); }); From 0a0165df456704a058fb6f95fa44707ae976e237 Mon Sep 17 00:00:00 2001 From: Alejandro Celaya Date: Sat, 22 Apr 2023 12:05:31 +0200 Subject: [PATCH 2/3] Update changelog --- CHANGELOG.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d5928ee8..0c7317fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,23 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org). +## [Unreleased] +### Added +* *Nothing* + +### Changed +* *Nothing* + +### Deprecated +* *Nothing* + +### Removed +* *Nothing* + +### Fixed +* [#826](https://github.com/shlinkio/shlink-web-client/issues/826) Fix generated short URLs CSV so that it can be used to import on Shlink. + + ## [3.10.0] - 2023-03-19 ### Added * [#807](https://github.com/shlinkio/shlink-web-client/issues/807) Add support for device-specific long-URLs when creating or editing short URLs. From 72e4a7b062fd39daace4d3ca1215b33b180ead95 Mon Sep 17 00:00:00 2001 From: Alejandro Celaya Date: Sat, 22 Apr 2023 12:09:15 +0200 Subject: [PATCH 3/3] Fix incorrect type --- test/common/services/ReportExporter.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/test/common/services/ReportExporter.test.ts b/test/common/services/ReportExporter.test.ts index 3d786787..8fdc9cce 100644 --- a/test/common/services/ReportExporter.test.ts +++ b/test/common/services/ReportExporter.test.ts @@ -53,6 +53,7 @@ describe('ReportExporter', () => { createdAt: '', longUrl: '', tags: '', + shortCode: '', }, ];