diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ef9dc8ada..98da1a783 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -96,7 +96,11 @@ jobs: if: ${{ !cancelled() }} - name: Run svelte checks - run: npm run check + run: npm run check:svelte + if: ${{ !cancelled() }} + + - name: Run tsc + run: npm run check:typescript if: ${{ !cancelled() }} - name: Run unit tests & coverage diff --git a/web/package.json b/web/package.json index 90673a3a3..09df801a1 100644 --- a/web/package.json +++ b/web/package.json @@ -6,9 +6,10 @@ "build": "vite build", "package": "svelte-kit package", "preview": "vite preview", - "check": "svelte-check --no-tsconfig --fail-on-warnings --ignore \"src/api/open-api\"", - "check:watch": "npm run check -- --watch", - "check:code": "npm run format && npm run lint && npm run check", + "check:svelte": "svelte-check --no-tsconfig --fail-on-warnings --ignore \"src/api/open-api\"", + "check:typescript": "tsc --noEmit", + "check:watch": "npm run check:svelte -- --watch", + "check:code": "npm run format && npm run lint && npm run check:svelte && npm run check:typescript", "check:all": "npm run check:code && npm run test:cov", "lint": "eslint . --max-warnings 0", "lint:fix": "npm run lint -- --fix", diff --git a/web/src/api/utils.ts b/web/src/api/utils.ts index c7fa62bfa..39c319901 100644 --- a/web/src/api/utils.ts +++ b/web/src/api/utils.ts @@ -1,6 +1,6 @@ -import { AxiosError, AxiosPromise } from 'axios'; +import type { AxiosError, AxiosPromise } from 'axios'; import { api } from './api'; -import { UserResponseDto } from './open-api'; +import type { UserResponseDto } from './open-api'; export type ApiError = AxiosError<{ message: string }>; diff --git a/web/src/hooks.server.ts b/web/src/hooks.server.ts index 959ed5e3e..8998257e7 100644 --- a/web/src/hooks.server.ts +++ b/web/src/hooks.server.ts @@ -1,6 +1,6 @@ -import type { Handle, HandleServerError } from '@sveltejs/kit'; -import { AxiosError, AxiosResponse } from 'axios'; import { env } from '$env/dynamic/public'; +import type { Handle, HandleServerError } from '@sveltejs/kit'; +import type { AxiosError, AxiosResponse } from 'axios'; import { ImmichApi } from './api/api'; export const handle = (async ({ event, resolve }) => { diff --git a/web/src/lib/components/admin-page/jobs/jobs-panel.svelte b/web/src/lib/components/admin-page/jobs/jobs-panel.svelte index 06a3d05a5..5930cfa41 100644 --- a/web/src/lib/components/admin-page/jobs/jobs-panel.svelte +++ b/web/src/lib/components/admin-page/jobs/jobs-panel.svelte @@ -3,10 +3,11 @@ notificationController, NotificationType } from '$lib/components/shared-components/notification/notification'; + import { AppRoute } from '$lib/constants'; import { handleError } from '$lib/utils/handle-error'; import { AllJobStatusResponseDto, api, JobCommand, JobCommandDto, JobName } from '@api'; import type { ComponentType } from 'svelte'; - import Icon from 'svelte-material-icons/DotsVertical.svelte'; + import type Icon from 'svelte-material-icons/DotsVertical.svelte'; import FaceRecognition from 'svelte-material-icons/FaceRecognition.svelte'; import FileJpgBox from 'svelte-material-icons/FileJpgBox.svelte'; import FileXmlBox from 'svelte-material-icons/FileXmlBox.svelte'; @@ -19,7 +20,6 @@ import ConfirmDialogue from '../../shared-components/confirm-dialogue.svelte'; import JobTile from './job-tile.svelte'; import StorageMigrationDescription from './storage-migration-description.svelte'; - import { AppRoute } from '$lib/constants'; export let jobs: AllJobStatusResponseDto; diff --git a/web/src/lib/components/admin-page/server-stats/server-stats-panel.svelte b/web/src/lib/components/admin-page/server-stats/server-stats-panel.svelte index c1b73f9a4..c1d26f115 100644 --- a/web/src/lib/components/admin-page/server-stats/server-stats-panel.svelte +++ b/web/src/lib/components/admin-page/server-stats/server-stats-panel.svelte @@ -1,11 +1,11 @@ <script lang="ts"> - import { ServerStatsResponseDto } from '@api'; - import CameraIris from 'svelte-material-icons/CameraIris.svelte'; - import PlayCircle from 'svelte-material-icons/PlayCircle.svelte'; - import Memory from 'svelte-material-icons/Memory.svelte'; - import StatsCard from './stats-card.svelte'; - import { asByteUnitString, getBytesWithUnit } from '../../../utils/byte-units'; import { locale } from '$lib/stores/preferences.store'; + import type { ServerStatsResponseDto } from '@api'; + import CameraIris from 'svelte-material-icons/CameraIris.svelte'; + import Memory from 'svelte-material-icons/Memory.svelte'; + import PlayCircle from 'svelte-material-icons/PlayCircle.svelte'; + import { asByteUnitString, getBytesWithUnit } from '../../../utils/byte-units'; + import StatsCard from './stats-card.svelte'; export let stats: ServerStatsResponseDto = { photos: 0, diff --git a/web/src/lib/components/admin-page/settings/storage-template/supported-datetime-panel.svelte b/web/src/lib/components/admin-page/settings/storage-template/supported-datetime-panel.svelte index 14c817b1e..d30798fb1 100644 --- a/web/src/lib/components/admin-page/settings/storage-template/supported-datetime-panel.svelte +++ b/web/src/lib/components/admin-page/settings/storage-template/supported-datetime-panel.svelte @@ -1,5 +1,5 @@ <script lang="ts"> - import { SystemConfigTemplateStorageOptionDto } from '@api'; + import type { SystemConfigTemplateStorageOptionDto } from '@api'; import * as luxon from 'luxon'; export let options: SystemConfigTemplateStorageOptionDto; diff --git a/web/src/lib/components/album-page/__tests__/album-card.spec.ts b/web/src/lib/components/album-page/__tests__/album-card.spec.ts index 1270e2f1b..ba7b194c5 100644 --- a/web/src/lib/components/album-page/__tests__/album-card.spec.ts +++ b/web/src/lib/components/album-page/__tests__/album-card.spec.ts @@ -37,7 +37,7 @@ describe('AlbumCard component', () => { ])( 'shows album data without thumbnail with count $count - shared: $shared', async ({ album, count, shared }) => { - sut = render(AlbumCard, { album }); + sut = render(AlbumCard, { album, user: album.owner }); const albumImgElement = sut.getByTestId('album-image'); const albumNameElement = sut.getByTestId('album-name'); @@ -58,10 +58,10 @@ describe('AlbumCard component', () => { ); it('shows album data and and loads the thumbnail image when available', async () => { - const thumbnailBlob = new Blob(); + const thumbnailFile = new File([new Blob()], 'fileThumbnail'); const thumbnailUrl = 'blob:thumbnailUrlOne'; apiMock.assetApi.getAssetThumbnail.mockResolvedValue({ - data: thumbnailBlob, + data: thumbnailFile, config: {}, headers: {}, status: 200, @@ -74,7 +74,7 @@ describe('AlbumCard component', () => { shared: false, albumName: 'some album name' }); - sut = render(AlbumCard, { album }); + sut = render(AlbumCard, { album, user: album.owner }); const albumImgElement = sut.getByTestId('album-image'); const albumNameElement = sut.getByTestId('album-name'); @@ -92,7 +92,7 @@ describe('AlbumCard component', () => { }, { responseType: 'blob' } ); - expect(createObjectURLMock).toHaveBeenCalledWith(thumbnailBlob); + expect(createObjectURLMock).toHaveBeenCalledWith(thumbnailFile); expect(albumNameElement).toHaveTextContent('some album name'); expect(albumDetailsElement).toHaveTextContent('0 items'); @@ -102,7 +102,7 @@ describe('AlbumCard component', () => { const album = Object.freeze(albumFactory.build({ albumThumbnailAssetId: null })); beforeEach(async () => { - sut = render(AlbumCard, { album }); + sut = render(AlbumCard, { album, user: album.owner }); const albumImgElement = sut.getByTestId('album-image'); await waitFor(() => expect(albumImgElement).toHaveAttribute('src')); diff --git a/web/src/lib/components/album-page/album-card.svelte b/web/src/lib/components/album-page/album-card.svelte index 8249810ca..5900abb03 100644 --- a/web/src/lib/components/album-page/album-card.svelte +++ b/web/src/lib/components/album-page/album-card.svelte @@ -1,23 +1,11 @@ -<script lang="ts" context="module"> - type OnShowContextMenu = { - showalbumcontextmenu: OnShowContextMenuDetail; - }; - - type OnClick = { - click: OnClickDetail; - }; - - export type OnShowContextMenuDetail = { x: number; y: number }; - export type OnClickDetail = AlbumResponseDto; -</script> - <script lang="ts"> + import noThumbnailUrl from '$lib/assets/no-thumbnail.png'; + import { locale } from '$lib/stores/preferences.store'; import { AlbumResponseDto, api, ThumbnailFormat, UserResponseDto } from '@api'; import { createEventDispatcher, onMount } from 'svelte'; import DotsVertical from 'svelte-material-icons/DotsVertical.svelte'; - import noThumbnailUrl from '$lib/assets/no-thumbnail.png'; - import { locale } from '$lib/stores/preferences.store'; import IconButton from '../elements/buttons/icon-button.svelte'; + import type { OnClick, OnShowContextMenu } from './album-card'; export let album: AlbumResponseDto; export let isSharingView = false; diff --git a/web/src/lib/components/album-page/album-card.ts b/web/src/lib/components/album-page/album-card.ts new file mode 100644 index 000000000..c69b7e6c3 --- /dev/null +++ b/web/src/lib/components/album-page/album-card.ts @@ -0,0 +1,12 @@ +import type { AlbumResponseDto } from '@api'; + +export type OnShowContextMenu = { + showalbumcontextmenu: OnShowContextMenuDetail; +}; + +export type OnClick = { + click: OnClickDetail; +}; + +export type OnShowContextMenuDetail = { x: number; y: number }; +export type OnClickDetail = AlbumResponseDto; diff --git a/web/src/lib/components/album-page/asset-selection.svelte b/web/src/lib/components/album-page/asset-selection.svelte index 82a9d3d94..6282da2c3 100644 --- a/web/src/lib/components/album-page/asset-selection.svelte +++ b/web/src/lib/components/album-page/asset-selection.svelte @@ -1,18 +1,18 @@ <script lang="ts"> - import { createEventDispatcher, onMount } from 'svelte'; - import { quintOut } from 'svelte/easing'; - import { fly } from 'svelte/transition'; - import { AssetResponseDto } from '@api'; - import { openFileUploadDialog } from '$lib/utils/file-uploader'; - import ControlAppBar from '../shared-components/control-app-bar.svelte'; - import AssetGrid from '../photos-page/asset-grid.svelte'; import { assetInteractionStore, assetsInAlbumStoreState, selectedAssets } from '$lib/stores/asset-interaction.store'; import { locale } from '$lib/stores/preferences.store'; + import { openFileUploadDialog } from '$lib/utils/file-uploader'; + import type { AssetResponseDto } from '@api'; + import { createEventDispatcher, onMount } from 'svelte'; + import { quintOut } from 'svelte/easing'; + import { fly } from 'svelte/transition'; import Button from '../elements/buttons/button.svelte'; + import AssetGrid from '../photos-page/asset-grid.svelte'; + import ControlAppBar from '../shared-components/control-app-bar.svelte'; const dispatch = createEventDispatcher(); diff --git a/web/src/lib/components/album-page/thumbnail-selection.svelte b/web/src/lib/components/album-page/thumbnail-selection.svelte index c2923002d..6486ad60e 100644 --- a/web/src/lib/components/album-page/thumbnail-selection.svelte +++ b/web/src/lib/components/album-page/thumbnail-selection.svelte @@ -1,11 +1,11 @@ <script lang="ts"> - import { AlbumResponseDto, AssetResponseDto } from '@api'; + import type { AlbumResponseDto, AssetResponseDto } from '@api'; import { createEventDispatcher } from 'svelte'; import { quintOut } from 'svelte/easing'; import { fly } from 'svelte/transition'; import Thumbnail from '../assets/thumbnail/thumbnail.svelte'; - import ControlAppBar from '../shared-components/control-app-bar.svelte'; import Button from '../elements/buttons/button.svelte'; + import ControlAppBar from '../shared-components/control-app-bar.svelte'; export let album: AlbumResponseDto; diff --git a/web/src/lib/components/asset-viewer/asset-viewer-nav-bar.svelte b/web/src/lib/components/asset-viewer/asset-viewer-nav-bar.svelte index daaea852b..302e6e361 100644 --- a/web/src/lib/components/asset-viewer/asset-viewer-nav-bar.svelte +++ b/web/src/lib/components/asset-viewer/asset-viewer-nav-bar.svelte @@ -1,23 +1,21 @@ <script lang="ts"> - import { createEventDispatcher } from 'svelte'; - + import { page } from '$app/stores'; import { clickOutside } from '$lib/utils/click-outside'; + import type { AssetResponseDto } from '@api'; + import { createEventDispatcher } from 'svelte'; import ArrowLeft from 'svelte-material-icons/ArrowLeft.svelte'; import CloudDownloadOutline from 'svelte-material-icons/CloudDownloadOutline.svelte'; - import InformationOutline from 'svelte-material-icons/InformationOutline.svelte'; - import DotsVertical from 'svelte-material-icons/DotsVertical.svelte'; + import ContentCopy from 'svelte-material-icons/ContentCopy.svelte'; import DeleteOutline from 'svelte-material-icons/DeleteOutline.svelte'; + import DotsVertical from 'svelte-material-icons/DotsVertical.svelte'; + import Heart from 'svelte-material-icons/Heart.svelte'; + import HeartOutline from 'svelte-material-icons/HeartOutline.svelte'; + import InformationOutline from 'svelte-material-icons/InformationOutline.svelte'; + import MotionPauseOutline from 'svelte-material-icons/MotionPauseOutline.svelte'; + import MotionPlayOutline from 'svelte-material-icons/MotionPlayOutline.svelte'; import CircleIconButton from '../elements/buttons/circle-icon-button.svelte'; import ContextMenu from '../shared-components/context-menu/context-menu.svelte'; import MenuOption from '../shared-components/context-menu/menu-option.svelte'; - import Heart from 'svelte-material-icons/Heart.svelte'; - import HeartOutline from 'svelte-material-icons/HeartOutline.svelte'; - import ContentCopy from 'svelte-material-icons/ContentCopy.svelte'; - import MotionPlayOutline from 'svelte-material-icons/MotionPlayOutline.svelte'; - import MotionPauseOutline from 'svelte-material-icons/MotionPauseOutline.svelte'; - - import { page } from '$app/stores'; - import { AssetResponseDto } from '../../../api'; export let asset: AssetResponseDto; export let showCopyButton: boolean; diff --git a/web/src/lib/components/forms/api-key-form.svelte b/web/src/lib/components/forms/api-key-form.svelte index a11317bed..dad32d61b 100644 --- a/web/src/lib/components/forms/api-key-form.svelte +++ b/web/src/lib/components/forms/api-key-form.svelte @@ -1,9 +1,9 @@ <script lang="ts"> - import { APIKeyResponseDto } from '@api'; + import type { APIKeyResponseDto } from '@api'; import { createEventDispatcher } from 'svelte'; import KeyVariant from 'svelte-material-icons/KeyVariant.svelte'; - import FullScreenModal from '../shared-components/full-screen-modal.svelte'; import Button from '../elements/buttons/button.svelte'; + import FullScreenModal from '../shared-components/full-screen-modal.svelte'; export let apiKey: Partial<APIKeyResponseDto>; export let title = 'API Key'; diff --git a/web/src/lib/components/map-page/map-settings-modal.svelte b/web/src/lib/components/map-page/map-settings-modal.svelte index 823536fc7..3d5fe5656 100644 --- a/web/src/lib/components/map-page/map-settings-modal.svelte +++ b/web/src/lib/components/map-page/map-settings-modal.svelte @@ -1,15 +1,6 @@ -<script lang="ts" context="module"> - export interface MapSettings { - allowDarkMode: boolean; - onlyFavorites: boolean; - relativeDate: string; - dateAfter: string; - dateBefore: string; - } -</script> - <script lang="ts"> import FullScreenModal from '$lib/components/shared-components/full-screen-modal.svelte'; + import type { MapSettings } from '$lib/stores/preferences.store'; import { Duration } from 'luxon'; import { createEventDispatcher } from 'svelte'; import { fly } from 'svelte/transition'; diff --git a/web/src/lib/components/photos-page/asset-date-group.svelte b/web/src/lib/components/photos-page/asset-date-group.svelte index 3b000d6a2..a9e704ab1 100644 --- a/web/src/lib/components/photos-page/asset-date-group.svelte +++ b/web/src/lib/components/photos-page/asset-date-group.svelte @@ -1,10 +1,4 @@ <script lang="ts"> - import { assetStore } from '$lib/stores/assets.store'; - import CheckCircle from 'svelte-material-icons/CheckCircle.svelte'; - import CircleOutline from 'svelte-material-icons/CircleOutline.svelte'; - import { fly } from 'svelte/transition'; - import { AssetResponseDto } from '@api'; - import lodash from 'lodash-es'; import { assetInteractionStore, assetsInAlbumStoreState, @@ -12,9 +6,15 @@ selectedAssets, selectedGroup } from '$lib/stores/asset-interaction.store'; + import { assetStore } from '$lib/stores/assets.store'; import { locale } from '$lib/stores/preferences.store'; - import Thumbnail from '../assets/thumbnail/thumbnail.svelte'; + import type { AssetResponseDto } from '@api'; + import lodash from 'lodash-es'; + import CheckCircle from 'svelte-material-icons/CheckCircle.svelte'; + import CircleOutline from 'svelte-material-icons/CircleOutline.svelte'; import { flip } from 'svelte/animate'; + import { fly } from 'svelte/transition'; + import Thumbnail from '../assets/thumbnail/thumbnail.svelte'; export let assets: AssetResponseDto[]; export let bucketDate: string; diff --git a/web/src/lib/components/photos-page/asset-grid.svelte b/web/src/lib/components/photos-page/asset-grid.svelte index dc2eac76c..0adbe217a 100644 --- a/web/src/lib/components/photos-page/asset-grid.svelte +++ b/web/src/lib/components/photos-page/asset-grid.svelte @@ -1,22 +1,21 @@ <script lang="ts"> - import { onDestroy, onMount } from 'svelte'; - - import { UserResponseDto } from '@api'; - import IntersectionObserver from '../asset-viewer/intersection-observer.svelte'; - import { assetGridState, assetStore, loadingBucketState } from '$lib/stores/assets.store'; - import { api, AssetCountByTimeBucketResponseDto, AssetResponseDto, TimeGroupEnum } from '@api'; - import AssetDateGroup from './asset-date-group.svelte'; - import Portal from '../shared-components/portal/portal.svelte'; - import AssetViewer from '../asset-viewer/asset-viewer.svelte'; import { assetInteractionStore, isViewingAssetStoreState, viewingAssetStoreState } from '$lib/stores/asset-interaction.store'; + import { assetGridState, assetStore, loadingBucketState } from '$lib/stores/assets.store'; + import type { UserResponseDto } from '@api'; + import { AssetCountByTimeBucketResponseDto, AssetResponseDto, TimeGroupEnum, api } from '@api'; + import { onDestroy, onMount } from 'svelte'; + import AssetViewer from '../asset-viewer/asset-viewer.svelte'; + import IntersectionObserver from '../asset-viewer/intersection-observer.svelte'; + import Portal from '../shared-components/portal/portal.svelte'; import Scrollbar, { OnScrollbarClickDetail, OnScrollbarDragDetail } from '../shared-components/scrollbar/scrollbar.svelte'; + import AssetDateGroup from './asset-date-group.svelte'; export let user: UserResponseDto | undefined = undefined; export let isAlbumSelectionMode = false; diff --git a/web/src/lib/components/photos-page/asset-select-control-bar.svelte b/web/src/lib/components/photos-page/asset-select-control-bar.svelte index ceb6c6aab..3e0f4bcca 100644 --- a/web/src/lib/components/photos-page/asset-select-control-bar.svelte +++ b/web/src/lib/components/photos-page/asset-select-control-bar.svelte @@ -17,7 +17,7 @@ <script lang="ts"> import { locale } from '$lib/stores/preferences.store'; - import { AssetResponseDto } from '@api'; + import type { AssetResponseDto } from '@api'; import Close from 'svelte-material-icons/Close.svelte'; import ControlAppBar from '../shared-components/control-app-bar.svelte'; diff --git a/web/src/lib/components/shared-components/create-share-link-modal/create-shared-link-modal.svelte b/web/src/lib/components/shared-components/create-share-link-modal/create-shared-link-modal.svelte index 8391467b6..32fb22d08 100644 --- a/web/src/lib/components/shared-components/create-share-link-modal/create-shared-link-modal.svelte +++ b/web/src/lib/components/shared-components/create-share-link-modal/create-shared-link-modal.svelte @@ -1,23 +1,23 @@ <script lang="ts"> - import { createEventDispatcher, onMount } from 'svelte'; - import BaseModal from '../base-modal.svelte'; - import Link from 'svelte-material-icons/Link.svelte'; - import { - AlbumResponseDto, - api, - AssetResponseDto, - SharedLinkResponseDto, - SharedLinkType - } from '@api'; - import { notificationController, NotificationType } from '../notification/notification'; - import { ImmichDropDownOption } from '../dropdown-button.svelte'; - import SettingSwitch from '$lib/components/admin-page/settings/setting-switch.svelte'; - import DropdownButton from '../dropdown-button.svelte'; import SettingInputField, { SettingInputFieldType } from '$lib/components/admin-page/settings/setting-input-field.svelte'; - import { handleError } from '$lib/utils/handle-error'; + import SettingSwitch from '$lib/components/admin-page/settings/setting-switch.svelte'; import Button from '$lib/components/elements/buttons/button.svelte'; + import { handleError } from '$lib/utils/handle-error'; + import { + AlbumResponseDto, + AssetResponseDto, + SharedLinkResponseDto, + SharedLinkType, + api + } from '@api'; + import { createEventDispatcher, onMount } from 'svelte'; + import Link from 'svelte-material-icons/Link.svelte'; + import BaseModal from '../base-modal.svelte'; + import type { ImmichDropDownOption } from '../dropdown-button.svelte'; + import DropdownButton from '../dropdown-button.svelte'; + import { NotificationType, notificationController } from '../notification/notification'; export let shareType: SharedLinkType; export let sharedAssets: AssetResponseDto[] = []; diff --git a/web/src/lib/components/shared-components/leaflet/marker-cluster/asset-marker-cluster.svelte b/web/src/lib/components/shared-components/leaflet/marker-cluster/asset-marker-cluster.svelte index dcd5ddece..15288b2a1 100644 --- a/web/src/lib/components/shared-components/leaflet/marker-cluster/asset-marker-cluster.svelte +++ b/web/src/lib/components/shared-components/leaflet/marker-cluster/asset-marker-cluster.svelte @@ -10,7 +10,7 @@ </script> <script lang="ts"> - import { MapMarkerResponseDto } from '@api'; + import type { MapMarkerResponseDto } from '@api'; import { DivIcon, LeafletEvent, LeafletMouseEvent, MarkerCluster, Point } from 'leaflet'; import 'leaflet.markercluster'; import { createEventDispatcher, onDestroy, onMount } from 'svelte'; diff --git a/web/src/lib/components/shared-components/navigation-bar/account-info-panel.svelte b/web/src/lib/components/shared-components/navigation-bar/account-info-panel.svelte index 719ed42de..c9efdeffa 100644 --- a/web/src/lib/components/shared-components/navigation-bar/account-info-panel.svelte +++ b/web/src/lib/components/shared-components/navigation-bar/account-info-panel.svelte @@ -1,12 +1,12 @@ <script lang="ts"> - import { UserResponseDto } from '@api'; + import Button from '$lib/components/elements/buttons/button.svelte'; + import { AppRoute } from '$lib/constants'; + import type { UserResponseDto } from '@api'; import { createEventDispatcher } from 'svelte'; - import { fade } from 'svelte/transition'; import Cog from 'svelte-material-icons/Cog.svelte'; import Logout from 'svelte-material-icons/Logout.svelte'; - import Button from '$lib/components/elements/buttons/button.svelte'; + import { fade } from 'svelte/transition'; import UserAvatar from '../user-avatar.svelte'; - import { AppRoute } from '$lib/constants'; export let user: UserResponseDto; diff --git a/web/src/lib/components/shared-components/upload-asset-preview.svelte b/web/src/lib/components/shared-components/upload-asset-preview.svelte index bccb1f79f..b417b85d6 100644 --- a/web/src/lib/components/shared-components/upload-asset-preview.svelte +++ b/web/src/lib/components/shared-components/upload-asset-preview.svelte @@ -1,9 +1,9 @@ <script lang="ts"> - import { fade } from 'svelte/transition'; - import { asByteUnitString } from '$lib/utils/byte-units'; - import { UploadAsset } from '$lib/models/upload-asset'; - import ImmichLogo from './immich-logo.svelte'; + import type { UploadAsset } from '$lib/models/upload-asset'; import { locale } from '$lib/stores/preferences.store'; + import { asByteUnitString } from '$lib/utils/byte-units'; + import { fade } from 'svelte/transition'; + import ImmichLogo from './immich-logo.svelte'; export let uploadAsset: UploadAsset; diff --git a/web/src/lib/components/user-settings-page/device-card.svelte b/web/src/lib/components/user-settings-page/device-card.svelte index 2b9003207..b55d54f7e 100644 --- a/web/src/lib/components/user-settings-page/device-card.svelte +++ b/web/src/lib/components/user-settings-page/device-card.svelte @@ -1,6 +1,6 @@ <script lang="ts"> import { locale } from '$lib/stores/preferences.store'; - import { AuthDeviceResponseDto } from '@api'; + import type { AuthDeviceResponseDto } from '@api'; import { DateTime, ToRelativeCalendarOptions } from 'luxon'; import { createEventDispatcher } from 'svelte'; import Android from 'svelte-material-icons/Android.svelte'; diff --git a/web/src/lib/models/asset-grid-state.ts b/web/src/lib/models/asset-grid-state.ts index 23e015edb..464fb5519 100644 --- a/web/src/lib/models/asset-grid-state.ts +++ b/web/src/lib/models/asset-grid-state.ts @@ -1,4 +1,4 @@ -import { AssetResponseDto } from '@api'; +import type { AssetResponseDto } from '@api'; export class AssetBucket { /** diff --git a/web/src/lib/stores/archived-asset.store.ts b/web/src/lib/stores/archived-asset.store.ts index 6168d29e9..4e478580d 100644 --- a/web/src/lib/stores/archived-asset.store.ts +++ b/web/src/lib/stores/archived-asset.store.ts @@ -1,4 +1,4 @@ -import { AssetResponseDto } from '@api'; +import type { AssetResponseDto } from '@api'; import { writable } from 'svelte/store'; export const archivedAsset = writable<AssetResponseDto[]>([]); diff --git a/web/src/lib/stores/preferences.store.ts b/web/src/lib/stores/preferences.store.ts index e5c6a154f..b0f491a3a 100644 --- a/web/src/lib/stores/preferences.store.ts +++ b/web/src/lib/stores/preferences.store.ts @@ -1,5 +1,4 @@ import { browser } from '$app/environment'; -import { MapSettings } from '$lib/components/map-page/map-settings-modal.svelte'; import { persisted } from 'svelte-local-storage-store'; const initialTheme = @@ -21,6 +20,14 @@ export const locale = persisted<string | undefined>('locale', undefined, { } }); +export interface MapSettings { + allowDarkMode: boolean; + onlyFavorites: boolean; + relativeDate: string; + dateAfter: string; + dateBefore: string; +} + export const mapSettings = persisted<MapSettings>('map-settings', { allowDarkMode: true, onlyFavorites: false, diff --git a/web/src/lib/utils/file-uploader.ts b/web/src/lib/utils/file-uploader.ts index e825d0eb7..9f91ff047 100644 --- a/web/src/lib/utils/file-uploader.ts +++ b/web/src/lib/utils/file-uploader.ts @@ -1,13 +1,13 @@ +import { uploadAssetsStore } from '$lib/stores/upload'; +import { addAssetsToAlbum, getFileMimeType, getFilenameExtension } from '$lib/utils/asset-utils'; +import type { AssetFileUploadResponseDto } from '@api'; +import axios from 'axios'; +import { combineLatestAll, filter, firstValueFrom, from, mergeMap, of } from 'rxjs'; +import type { UploadAsset } from '../models/upload-asset'; import { notificationController, NotificationType } from './../components/shared-components/notification/notification'; -import { uploadAssetsStore } from '$lib/stores/upload'; -import type { UploadAsset } from '../models/upload-asset'; -import { AssetFileUploadResponseDto } from '@api'; -import { addAssetsToAlbum, getFileMimeType, getFilenameExtension } from '$lib/utils/asset-utils'; -import { mergeMap, filter, firstValueFrom, from, of, combineLatestAll } from 'rxjs'; -import axios from 'axios'; export const openFileUploadDialog = async ( albumId: string | undefined = undefined, diff --git a/web/src/lib/utils/handle-error.ts b/web/src/lib/utils/handle-error.ts index 5751ef909..853b88758 100644 --- a/web/src/lib/utils/handle-error.ts +++ b/web/src/lib/utils/handle-error.ts @@ -1,4 +1,4 @@ -import { ApiError } from '../../api'; +import type { ApiError } from '@api'; import { notificationController, NotificationType diff --git a/web/src/routes/(user)/albums/albums.bloc.ts b/web/src/routes/(user)/albums/albums.bloc.ts index ceca7db14..537ce33f1 100644 --- a/web/src/routes/(user)/albums/albums.bloc.ts +++ b/web/src/routes/(user)/albums/albums.bloc.ts @@ -1,10 +1,10 @@ +import type { OnShowContextMenuDetail } from '$lib/components/album-page/album-card'; import { notificationController, NotificationType } from '$lib/components/shared-components/notification/notification'; import { AlbumResponseDto, api } from '@api'; -import { OnShowContextMenuDetail } from '$lib/components/album-page/album-card.svelte'; -import { writable, derived, get } from 'svelte/store'; +import { derived, get, writable } from 'svelte/store'; type AlbumsProps = { albums: AlbumResponseDto[] }; diff --git a/web/src/routes/(user)/search/+page.svelte b/web/src/routes/(user)/search/+page.svelte index 1c215834f..f4230b8c0 100644 --- a/web/src/routes/(user)/search/+page.svelte +++ b/web/src/routes/(user)/search/+page.svelte @@ -12,7 +12,7 @@ import ControlAppBar from '$lib/components/shared-components/control-app-bar.svelte'; import GalleryViewer from '$lib/components/shared-components/gallery-viewer/gallery-viewer.svelte'; import SearchBar from '$lib/components/shared-components/search-bar/search-bar.svelte'; - import { AssetResponseDto } from '@api'; + import type { AssetResponseDto } from '@api'; import ArrowLeft from 'svelte-material-icons/ArrowLeft.svelte'; import DotsVertical from 'svelte-material-icons/DotsVertical.svelte'; import ImageOffOutline from 'svelte-material-icons/ImageOffOutline.svelte'; diff --git a/web/src/test-data/factories/album-factory.ts b/web/src/test-data/factories/album-factory.ts index 2b01054d9..fc0861d21 100644 --- a/web/src/test-data/factories/album-factory.ts +++ b/web/src/test-data/factories/album-factory.ts @@ -1,6 +1,7 @@ -import { AlbumResponseDto } from '@api'; -import { Sync } from 'factory.ts'; +import type { AlbumResponseDto } from '@api'; import { faker } from '@faker-js/faker'; +import { Sync } from 'factory.ts'; +import { userFactory } from './user-factory'; export const albumFactory = Sync.makeFactory<AlbumResponseDto>({ albumName: Sync.each(() => faker.commerce.product()), @@ -8,8 +9,10 @@ export const albumFactory = Sync.makeFactory<AlbumResponseDto>({ assetCount: Sync.each((i) => i % 5), assets: [], createdAt: Sync.each(() => faker.date.past().toISOString()), + updatedAt: Sync.each(() => faker.date.past().toISOString()), id: Sync.each(() => faker.datatype.uuid()), ownerId: Sync.each(() => faker.datatype.uuid()), + owner: userFactory.build(), shared: false, sharedUsers: [] }); diff --git a/web/src/test-data/factories/user-factory.ts b/web/src/test-data/factories/user-factory.ts new file mode 100644 index 000000000..f4e5b21eb --- /dev/null +++ b/web/src/test-data/factories/user-factory.ts @@ -0,0 +1,18 @@ +import type { UserResponseDto } from '@api'; +import { faker } from '@faker-js/faker'; +import { Sync } from 'factory.ts'; + +export const userFactory = Sync.makeFactory<UserResponseDto>({ + id: Sync.each(() => faker.datatype.uuid()), + email: Sync.each(() => faker.internet.email()), + firstName: Sync.each(() => faker.name.firstName()), + lastName: Sync.each(() => faker.name.lastName()), + storageLabel: Sync.each(() => faker.random.alphaNumeric()), + profileImagePath: '', + shouldChangePassword: Sync.each(() => faker.datatype.boolean()), + isAdmin: true, + createdAt: Sync.each(() => faker.date.past().toISOString()), + deletedAt: null, + updatedAt: Sync.each(() => faker.date.past().toISOString()), + oauthId: '' +}); diff --git a/web/tsconfig.json b/web/tsconfig.json index c9b1460dc..a118602cd 100644 --- a/web/tsconfig.json +++ b/web/tsconfig.json @@ -16,7 +16,6 @@ "sourceMap": true, "strict": true, "target": "es2020", - "importsNotUsedAsValues": "preserve", "preserveValueImports": false, "paths": { "$lib": [