From f6f82a56623fdb11098086fdaaf6b726aec37749 Mon Sep 17 00:00:00 2001 From: Jason Rasmussen Date: Wed, 22 May 2024 09:33:37 -0400 Subject: [PATCH] feat(web): s (#9663) --- web/src/lib/components/album-page/album-card.svelte | 3 ++- .../components/faces-page/unmerge-face-selector.svelte | 5 +++-- .../lib/components/forms/library-import-paths-form.svelte | 8 ++------ .../photos-page/actions/remove-from-album.svelte | 3 ++- .../lib/components/photos-page/delete-asset-dialog.svelte | 3 ++- .../lib/components/shared-components/upload-panel.svelte | 5 +++-- web/src/lib/utils.ts | 4 +++- web/src/lib/utils/asset-utils.ts | 8 ++++---- .../[[photos=photos]]/[[assetId=id]]/+page.svelte | 4 ++-- .../[[photos=photos]]/[[assetId=id]]/+page.svelte | 4 ++-- 10 files changed, 25 insertions(+), 22 deletions(-) diff --git a/web/src/lib/components/album-page/album-card.svelte b/web/src/lib/components/album-page/album-card.svelte index 6bd5f85485..6d64783e38 100644 --- a/web/src/lib/components/album-page/album-card.svelte +++ b/web/src/lib/components/album-page/album-card.svelte @@ -7,6 +7,7 @@ import { getShortDateRange } from '$lib/utils/date-time'; import AlbumCover from '$lib/components/album-page/album-cover.svelte'; import CircleIconButton from '$lib/components/elements/buttons/circle-icon-button.svelte'; + import { s } from '$lib/utils'; export let album: AlbumResponseDto; export let showOwner = false; @@ -65,7 +66,7 @@ {#if showItemCount}

{album.assetCount.toLocaleString($locale)} - {album.assetCount === 1 ? `item` : `items`} + item{s(album.assetCount)}

{/if} diff --git a/web/src/lib/components/faces-page/unmerge-face-selector.svelte b/web/src/lib/components/faces-page/unmerge-face-selector.svelte index 2343df68c9..1e480f85db 100644 --- a/web/src/lib/components/faces-page/unmerge-face-selector.svelte +++ b/web/src/lib/components/faces-page/unmerge-face-selector.svelte @@ -19,6 +19,7 @@ import { NotificationType, notificationController } from '../shared-components/notification/notification'; import FaceThumbnail from './face-thumbnail.svelte'; import PeopleList from './people-list.svelte'; + import { s } from '$lib/utils'; export let assetIds: string[]; export let personAssets: PersonResponseDto; @@ -76,7 +77,7 @@ await reassignFaces({ id: data.id, assetFaceUpdateDto: { data: selectedPeople } }); notificationController.show({ - message: `Re-assigned ${assetIds.length} asset${assetIds.length > 1 ? 's' : ''} to a new person`, + message: `Re-assigned ${assetIds.length} asset${s(assetIds.length)} to a new person`, type: NotificationType.Info, }); } catch (error) { @@ -96,7 +97,7 @@ if (selectedPerson) { await reassignFaces({ id: selectedPerson.id, assetFaceUpdateDto: { data: selectedPeople } }); notificationController.show({ - message: `Re-assigned ${assetIds.length} asset${assetIds.length > 1 ? 's' : ''} to ${ + message: `Re-assigned ${assetIds.length} asset${s(assetIds.length)} to ${ selectedPerson.name || 'an existing person' }`, type: NotificationType.Info, diff --git a/web/src/lib/components/forms/library-import-paths-form.svelte b/web/src/lib/components/forms/library-import-paths-form.svelte index dca565ce31..be832a63a3 100644 --- a/web/src/lib/components/forms/library-import-paths-form.svelte +++ b/web/src/lib/components/forms/library-import-paths-form.svelte @@ -9,6 +9,7 @@ import type { ValidateLibraryImportPathResponseDto } from '@immich/sdk'; import { NotificationType, notificationController } from '../shared-components/notification/notification'; import CircleIconButton from '$lib/components/elements/buttons/circle-icon-button.svelte'; + import { s } from '$lib/utils'; export let library: LibraryResponseDto; @@ -56,14 +57,9 @@ type: NotificationType.Info, }); } - } else if (failedPaths === 1) { - notificationController.show({ - message: `${failedPaths} path failed validation`, - type: NotificationType.Warning, - }); } else { notificationController.show({ - message: `${failedPaths} paths failed validation`, + message: `${failedPaths} path${s(failedPaths)} failed validation`, type: NotificationType.Warning, }); } diff --git a/web/src/lib/components/photos-page/actions/remove-from-album.svelte b/web/src/lib/components/photos-page/actions/remove-from-album.svelte index c6db3e077a..89385327a5 100644 --- a/web/src/lib/components/photos-page/actions/remove-from-album.svelte +++ b/web/src/lib/components/photos-page/actions/remove-from-album.svelte @@ -9,6 +9,7 @@ import { mdiDeleteOutline, mdiImageRemoveOutline } from '@mdi/js'; import MenuOption from '../../shared-components/context-menu/menu-option.svelte'; import { getAssetControlContext } from '../asset-select-control-bar.svelte'; + import { s } from '$lib/utils'; export let album: AlbumResponseDto; export let onRemove: ((assetIds: string[]) => void) | undefined; @@ -33,7 +34,7 @@ const count = results.filter(({ success }) => success).length; notificationController.show({ type: NotificationType.Info, - message: `Removed ${count} asset${count === 1 ? '' : 's'}`, + message: `Removed ${count} asset${s(count)}`, }); clearSelect(); diff --git a/web/src/lib/components/photos-page/delete-asset-dialog.svelte b/web/src/lib/components/photos-page/delete-asset-dialog.svelte index 6338ff875f..22a1855ab4 100644 --- a/web/src/lib/components/photos-page/delete-asset-dialog.svelte +++ b/web/src/lib/components/photos-page/delete-asset-dialog.svelte @@ -3,6 +3,7 @@ import ConfirmDialogue from '../shared-components/confirm-dialogue.svelte'; import { showDeleteModal } from '$lib/stores/preferences.store'; import Checkbox from '$lib/components/elements/checkbox.svelte'; + import { s } from '$lib/utils'; export let size: number; @@ -23,7 +24,7 @@ dispatch('cancel')} diff --git a/web/src/lib/components/shared-components/upload-panel.svelte b/web/src/lib/components/shared-components/upload-panel.svelte index bbcba662b3..7793fd5a1c 100644 --- a/web/src/lib/components/shared-components/upload-panel.svelte +++ b/web/src/lib/components/shared-components/upload-panel.svelte @@ -8,6 +8,7 @@ import { uploadExecutionQueue } from '$lib/utils/file-uploader'; import CircleIconButton from '../elements/buttons/circle-icon-button.svelte'; import { mdiCog, mdiWindowMinimize, mdiCancel, mdiCloudUploadOutline } from '@mdi/js'; + import { s } from '$lib/utils'; let showDetail = false; let showOptions = false; @@ -36,7 +37,7 @@ on:outroend={() => { if ($errorCounter > 0) { notificationController.show({ - message: `Upload completed with ${$errorCounter} error${$errorCounter > 1 ? 's' : ''}, refresh the page to see new upload assets.`, + message: `Upload completed with ${$errorCounter} error${s($errorCounter)}, refresh the page to see new upload assets.`, type: NotificationType.Warning, }); } else if ($successCounter > 0) { @@ -47,7 +48,7 @@ } if ($duplicateCounter > 0) { notificationController.show({ - message: `Skipped ${$duplicateCounter} duplicate asset${$duplicateCounter > 1 ? 's' : ''}`, + message: `Skipped ${$duplicateCounter} duplicate asset${s($duplicateCounter)}`, type: NotificationType.Warning, }); } diff --git a/web/src/lib/utils.ts b/web/src/lib/utils.ts index 87cef15737..2baabd0a44 100644 --- a/web/src/lib/utils.ts +++ b/web/src/lib/utils.ts @@ -279,4 +279,6 @@ export const handlePromiseError = (promise: Promise): void => { promise.catch((error) => console.error(`[utils.ts]:handlePromiseError ${error}`, error)); }; -export const memoryLaneTitle = (yearsAgo: number) => `${yearsAgo} ${yearsAgo ? 'years' : 'year'} ago`; +export const s = (count: number) => (count === 1 ? '' : 's'); + +export const memoryLaneTitle = (yearsAgo: number) => `year${s(yearsAgo)} ago`; diff --git a/web/src/lib/utils/asset-utils.ts b/web/src/lib/utils/asset-utils.ts index 7a8bff68b2..dc29375ddd 100644 --- a/web/src/lib/utils/asset-utils.ts +++ b/web/src/lib/utils/asset-utils.ts @@ -5,7 +5,7 @@ import type { AssetInteractionStore } from '$lib/stores/asset-interaction.store' import { assetViewingStore } from '$lib/stores/asset-viewing.store'; import { BucketPosition, isSelectingAllAssets, type AssetStore } from '$lib/stores/assets.store'; import { downloadManager } from '$lib/stores/download'; -import { downloadRequest, getKey } from '$lib/utils'; +import { downloadRequest, getKey, s } from '$lib/utils'; import { createAlbum } from '$lib/utils/album-utils'; import { encodeHTMLSpecialChars } from '$lib/utils/string-utils'; import { @@ -38,7 +38,7 @@ export const addAssetsToAlbum = async (albumId: string, assetIds: string[]) => { timeout: 5000, message: count > 0 - ? `Added ${count} asset${count === 1 ? '' : 's'} to the album` + ? `Added ${count} asset${s(count)} to the album` : `Asset${assetIds.length === 1 ? ' was' : 's were'} already part of the album`, button: { text: 'View Album', @@ -58,7 +58,7 @@ export const addAssetsToNewAlbum = async (albumName: string, assetIds: string[]) notificationController.show({ type: NotificationType.Info, timeout: 5000, - message: `Added ${assetIds.length} asset${assetIds.length === 1 ? '' : 's'} to ${displayName}`, + message: `Added ${assetIds.length} asset${s(assetIds.length)} to ${displayName}`, html: true, button: { text: 'View Album', @@ -267,7 +267,7 @@ export const getSelectedAssets = (assets: Set, user: UserRespo const numberOfIssues = [...assets].filter((a) => user && a.ownerId !== user.id).length; if (numberOfIssues > 0) { notificationController.show({ - message: `Can't change metadata of ${numberOfIssues} asset${numberOfIssues > 1 ? 's' : ''}`, + message: `Can't change metadata of ${numberOfIssues} asset${s(numberOfIssues)}`, type: NotificationType.Warning, }); } diff --git a/web/src/routes/(user)/albums/[albumId=id]/[[photos=photos]]/[[assetId=id]]/+page.svelte b/web/src/routes/(user)/albums/[albumId=id]/[[photos=photos]]/[[assetId=id]]/+page.svelte index 4c57a9b967..c4e859fc3d 100644 --- a/web/src/routes/(user)/albums/[albumId=id]/[[photos=photos]]/[[assetId=id]]/+page.svelte +++ b/web/src/routes/(user)/albums/[albumId=id]/[[photos=photos]]/[[assetId=id]]/+page.svelte @@ -42,7 +42,7 @@ import { locale } from '$lib/stores/preferences.store'; import { SlideshowNavigation, SlideshowState, slideshowStore } from '$lib/stores/slideshow.store'; import { user } from '$lib/stores/user.store'; - import { handlePromiseError } from '$lib/utils'; + import { handlePromiseError, s } from '$lib/utils'; import { downloadAlbum } from '$lib/utils/asset-utils'; import { clickOutside } from '$lib/utils/click-outside'; import { getContextMenuPosition } from '$lib/utils/context-menu'; @@ -291,7 +291,7 @@ const count = results.filter(({ success }) => success).length; notificationController.show({ type: NotificationType.Info, - message: `Added ${count} asset${count === 1 ? '' : 's'}`, + message: `Added ${count} asset${s(count)}`, }); await refreshAlbum(); diff --git a/web/src/routes/(user)/people/[personId]/[[photos=photos]]/[[assetId=id]]/+page.svelte b/web/src/routes/(user)/people/[personId]/[[photos=photos]]/[[assetId=id]]/+page.svelte index fcf31584f4..b87af4d37f 100644 --- a/web/src/routes/(user)/people/[personId]/[[photos=photos]]/[[assetId=id]]/+page.svelte +++ b/web/src/routes/(user)/people/[personId]/[[photos=photos]]/[[assetId=id]]/+page.svelte @@ -31,7 +31,7 @@ import { assetViewingStore } from '$lib/stores/asset-viewing.store'; import { AssetStore } from '$lib/stores/assets.store'; import { websocketEvents } from '$lib/stores/websocket'; - import { getPeopleThumbnailUrl, handlePromiseError } from '$lib/utils'; + import { getPeopleThumbnailUrl, handlePromiseError, s } from '$lib/utils'; import { clickOutside } from '$lib/utils/click-outside'; import { handleError } from '$lib/utils/handle-error'; import { isExternalUrl } from '$lib/utils/navigation'; @@ -482,7 +482,7 @@ {#if data.person.name}

{data.person.name}

- {`${numberOfAssets} asset${numberOfAssets > 1 ? 's' : ''}`} + {`${numberOfAssets} asset${s(numberOfAssets)}`}

{:else}

Add a name