refactor(web): use new open api client (#7097)

* refactor(web): use new open api client

* refactor: remove activity api

* refactor: trash, oauth, and partner apis

* refactor: job api

* refactor: face, library, system config

* refactor: user api

* refactor: album api
This commit is contained in:
Jason Rasmussen 2024-02-13 17:07:37 -05:00 committed by GitHub
parent 9b4a770b9d
commit 8fd94211c0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
66 changed files with 593 additions and 850 deletions

View file

@ -3,7 +3,8 @@
notificationController,
NotificationType,
} from '$lib/components/shared-components/notification/notification';
import { api, type ApiError } from '@api';
import { type ApiError } from '@api';
import { changePassword } from '@immich/sdk';
import { fade } from 'svelte/transition';
import SettingInputField, { SettingInputFieldType } from '../admin-page/settings/setting-input-field.svelte';
import Button from '../elements/buttons/button.svelte';
@ -14,12 +15,7 @@
const handleChangePassword = async () => {
try {
await api.authenticationApi.changePassword({
changePasswordDto: {
password,
newPassword,
},
});
await changePassword({ changePasswordDto: { password, newPassword } });
notificationController.show({
message: 'Updated password',

View file

@ -1,5 +1,6 @@
<script lang="ts">
import { api, type AuthDeviceResponseDto } from '@api';
import { type AuthDeviceResponseDto } from '@api';
import { getAuthDevices, logoutAuthDevice, logoutAuthDevices } from '@immich/sdk';
import { handleError } from '../../utils/handle-error';
import Button from '../elements/buttons/button.svelte';
import ConfirmDialogue from '../shared-components/confirm-dialogue.svelte';
@ -10,7 +11,7 @@
let deleteDevice: AuthDeviceResponseDto | null = null;
let deleteAll = false;
const refresh = () => api.authenticationApi.getAuthDevices().then(({ data }) => (devices = data));
const refresh = () => getAuthDevices().then((_devices) => (devices = _devices));
$: currentDevice = devices.find((device) => device.current);
$: otherDevices = devices.filter((device) => !device.current);
@ -21,7 +22,7 @@
}
try {
await api.authenticationApi.logoutAuthDevice({ id: deleteDevice.id });
await logoutAuthDevice({ id: deleteDevice.id });
notificationController.show({ message: `Logged out device`, type: NotificationType.Info });
} catch (error) {
handleError(error, 'Unable to log out device');
@ -33,7 +34,7 @@
const handleDeleteAll = async () => {
try {
await api.authenticationApi.logoutAuthDevices();
await logoutAuthDevices();
notificationController.show({
message: `Logged out all devices`,
type: NotificationType.Info,

View file

@ -1,23 +1,31 @@
<script lang="ts">
import { api, type LibraryResponseDto, LibraryType, type LibraryStatsResponseDto } from '@api';
import { onMount } from 'svelte';
import Button from '../elements/buttons/button.svelte';
import { notificationController, NotificationType } from '../shared-components/notification/notification';
import ConfirmDialogue from '../shared-components/confirm-dialogue.svelte';
import { handleError } from '$lib/utils/handle-error';
import { fade } from 'svelte/transition';
import Icon from '$lib/components/elements/icon.svelte';
import { slide } from 'svelte/transition';
import LibraryImportPathsForm from '../forms/library-import-paths-form.svelte';
import LibraryScanSettingsForm from '../forms/library-scan-settings-form.svelte';
import LibraryRenameForm from '../forms/library-rename-form.svelte';
import LoadingSpinner from '$lib/components/shared-components/loading-spinner.svelte';
import { getBytesWithUnit } from '$lib/utils/byte-units';
import Portal from '../shared-components/portal/portal.svelte';
import { getContextMenuPosition } from '$lib/utils/context-menu';
import { handleError } from '$lib/utils/handle-error';
import { LibraryType, type LibraryResponseDto, type LibraryStatsResponseDto } from '@api';
import {
createLibrary,
deleteLibrary,
getLibraries,
getLibraryStatistics,
removeOfflineFiles,
scanLibrary,
updateLibrary,
} from '@immich/sdk';
import { mdiDatabase, mdiDotsVertical, mdiUpload } from '@mdi/js';
import { onMount } from 'svelte';
import { fade, slide } from 'svelte/transition';
import Button from '../elements/buttons/button.svelte';
import LibraryImportPathsForm from '../forms/library-import-paths-form.svelte';
import LibraryRenameForm from '../forms/library-rename-form.svelte';
import LibraryScanSettingsForm from '../forms/library-scan-settings-form.svelte';
import ConfirmDialogue from '../shared-components/confirm-dialogue.svelte';
import ContextMenu from '../shared-components/context-menu/context-menu.svelte';
import MenuOption from '../shared-components/context-menu/menu-option.svelte';
import { getContextMenuPosition } from '$lib/utils/context-menu';
import { mdiDatabase, mdiDotsVertical, mdiUpload } from '@mdi/js';
import LoadingSpinner from '$lib/components/shared-components/loading-spinner.svelte';
import { NotificationType, notificationController } from '../shared-components/notification/notification';
import Portal from '../shared-components/portal/portal.svelte';
let libraries: LibraryResponseDto[] = [];
@ -29,7 +37,7 @@
let diskUsageUnit: string[] = [];
let confirmDeleteLibrary: LibraryResponseDto | null = null;
let deleteLibrary: LibraryResponseDto | null = null;
let deletedLibrary: LibraryResponseDto | null = null;
let editImportPaths: number | null;
let editScanSettings: number | null;
@ -73,8 +81,7 @@
showContextMenu = false;
};
const refreshStats = async (listIndex: number) => {
const { data } = await api.libraryApi.getLibraryStatistics({ id: libraries[listIndex].id });
stats[listIndex] = data;
stats[listIndex] = await getLibraryStatistics({ id: libraries[listIndex].id });
photos[listIndex] = stats[listIndex].photos;
videos[listIndex] = stats[listIndex].videos;
totalCount[listIndex] = stats[listIndex].total;
@ -82,8 +89,7 @@
};
async function readLibraryList() {
const { data } = await api.libraryApi.getLibraries();
libraries = data;
libraries = await getLibraries();
dropdownOpen.length = libraries.length;
@ -95,12 +101,10 @@
const handleCreate = async (libraryType: LibraryType) => {
try {
const { data } = await api.libraryApi.createLibrary({
const createdLibrary = await createLibrary({
createLibraryDto: { type: libraryType },
});
const createdLibrary = data;
notificationController.show({
message: `Created library: ${createdLibrary.name}`,
type: NotificationType.Info,
@ -119,7 +123,7 @@
try {
const libraryId = libraries[updateLibraryIndex].id;
await api.libraryApi.updateLibrary({ id: libraryId, updateLibraryDto: { ...event } });
await updateLibrary({ id: libraryId, updateLibraryDto: { ...event } });
} catch (error) {
handleError(error, 'Unable to update library');
} finally {
@ -130,15 +134,15 @@
const handleDelete = async () => {
if (confirmDeleteLibrary) {
deleteLibrary = confirmDeleteLibrary;
deletedLibrary = confirmDeleteLibrary;
}
if (!deleteLibrary) {
if (!deletedLibrary) {
return;
}
try {
await api.libraryApi.deleteLibrary({ id: deleteLibrary.id });
await deleteLibrary({ id: deletedLibrary.id });
notificationController.show({
message: `Library deleted`,
type: NotificationType.Info,
@ -147,7 +151,7 @@
handleError(error, 'Unable to remove library');
} finally {
confirmDeleteLibrary = null;
deleteLibrary = null;
deletedLibrary = null;
await readLibraryList();
}
};
@ -156,7 +160,7 @@
try {
for (const library of libraries) {
if (library.type === LibraryType.External) {
await api.libraryApi.scanLibrary({ id: library.id, scanLibraryDto: {} });
await scanLibrary({ id: library.id, scanLibraryDto: {} });
}
}
notificationController.show({
@ -170,7 +174,7 @@
const handleScan = async (libraryId: string) => {
try {
await api.libraryApi.scanLibrary({ id: libraryId, scanLibraryDto: {} });
await scanLibrary({ id: libraryId, scanLibraryDto: {} });
notificationController.show({
message: `Scanning library for new files`,
type: NotificationType.Info,
@ -182,7 +186,7 @@
const handleScanChanges = async (libraryId: string) => {
try {
await api.libraryApi.scanLibrary({ id: libraryId, scanLibraryDto: { refreshModifiedFiles: true } });
await scanLibrary({ id: libraryId, scanLibraryDto: { refreshModifiedFiles: true } });
notificationController.show({
message: `Scanning library for changed files`,
type: NotificationType.Info,
@ -194,7 +198,7 @@
const handleForceScan = async (libraryId: string) => {
try {
await api.libraryApi.scanLibrary({ id: libraryId, scanLibraryDto: { refreshAllFiles: true } });
await scanLibrary({ id: libraryId, scanLibraryDto: { refreshAllFiles: true } });
notificationController.show({
message: `Forcing refresh of all library files`,
type: NotificationType.Info,
@ -206,7 +210,7 @@
const handleRemoveOffline = async (libraryId: string) => {
try {
await api.libraryApi.removeOfflineFiles({ id: libraryId });
await removeOfflineFiles({ id: libraryId });
notificationController.show({
message: `Removing Offline Files`,
type: NotificationType.Info,
@ -272,7 +276,7 @@
deleteAssetCount = totalCount[selectedLibraryIndex];
confirmDeleteLibrary = selectedLibrary;
} else {
deleteLibrary = selectedLibrary;
deletedLibrary = selectedLibrary;
handleDelete();
}
}

View file

@ -3,7 +3,8 @@
notificationController,
NotificationType,
} from '$lib/components/shared-components/notification/notification';
import { api, type UserResponseDto } from '@api';
import { type UserResponseDto } from '@api';
import { updateUser } from '@immich/sdk';
import { fade } from 'svelte/transition';
import { handleError } from '../../utils/handle-error';
import SettingSwitch from '../admin-page/settings/setting-switch.svelte';
@ -13,7 +14,7 @@
const handleSave = async () => {
try {
const { data } = await api.userApi.updateUser({
const data = await updateUser({
updateUserDto: {
id: user.id,
memoriesEnabled: user.memoriesEnabled,

View file

@ -18,8 +18,7 @@
try {
loading = true;
const { data } = await oauth.link(window.location);
user = data;
user = await oauth.link(window.location);
notificationController.show({
message: 'Linked OAuth account',
@ -37,8 +36,7 @@
const handleUnlink = async () => {
try {
const { data } = await oauth.unlink();
user = data;
user = await oauth.unlink();
notificationController.show({
message: 'Unlinked OAuth account',
type: NotificationType.Info,

View file

@ -1,10 +1,11 @@
<script lang="ts">
import { api, type UserResponseDto } from '@api';
import BaseModal from '../shared-components/base-modal.svelte';
import UserAvatar from '../shared-components/user-avatar.svelte';
import ImmichLogo from '../shared-components/immich-logo.svelte';
import Button from '../elements/buttons/button.svelte';
import { type UserResponseDto } from '@api';
import { getAllUsers, getPartners } from '@immich/sdk';
import { createEventDispatcher, onMount } from 'svelte';
import Button from '../elements/buttons/button.svelte';
import BaseModal from '../shared-components/base-modal.svelte';
import ImmichLogo from '../shared-components/immich-logo.svelte';
import UserAvatar from '../shared-components/user-avatar.svelte';
export let user: UserResponseDto;
@ -15,13 +16,13 @@
onMount(async () => {
// TODO: update endpoint to have a query param for deleted users
let { data: users } = await api.userApi.getAllUsers({ isAll: false });
let users = await getAllUsers({ isAll: false });
// remove invalid users
users = users.filter((_user) => !(_user.deletedAt || _user.id === user.id));
// exclude partners from the list of users available for selection
const { data: partners } = await api.partnerApi.getPartners({ direction: 'shared-by' });
const partners = await getPartners({ direction: 'shared-by' });
const partnerIds = new Set(partners.map((partner) => partner.id));
availableUsers = users.filter((user) => !partnerIds.has(user.id));
});

View file

@ -1,15 +1,16 @@
<script lang="ts">
import { type PartnerResponseDto, type UserResponseDto, api } from '@api';
import UserAvatar from '../shared-components/user-avatar.svelte';
import Button from '../elements/buttons/button.svelte';
import PartnerSelectionModal from './partner-selection-modal.svelte';
import { handleError } from '../../utils/handle-error';
import ConfirmDialogue from '../shared-components/confirm-dialogue.svelte';
import CircleIconButton from '../elements/buttons/circle-icon-button.svelte';
import { type PartnerResponseDto, type UserResponseDto } from '@api';
import { createPartner, getPartners, removePartner, updatePartner } from '@immich/sdk';
import { mdiCheck, mdiClose } from '@mdi/js';
import { onMount } from 'svelte';
import Icon from '../elements/icon.svelte';
import { handleError } from '../../utils/handle-error';
import SettingSwitch from '../admin-page/settings/setting-switch.svelte';
import Button from '../elements/buttons/button.svelte';
import CircleIconButton from '../elements/buttons/circle-icon-button.svelte';
import Icon from '../elements/icon.svelte';
import ConfirmDialogue from '../shared-components/confirm-dialogue.svelte';
import UserAvatar from '../shared-components/user-avatar.svelte';
import PartnerSelectionModal from './partner-selection-modal.svelte';
interface PartnerSharing {
user: UserResponseDto;
@ -20,8 +21,8 @@
export let user: UserResponseDto;
let createPartner = false;
let removePartner: PartnerResponseDto | null = null;
let createPartnerFlag = false;
let removePartnerDto: PartnerResponseDto | null = null;
let partners: Array<PartnerSharing> = [];
onMount(() => {
@ -31,9 +32,9 @@
const refreshPartners = async () => {
partners = [];
const [{ data: sharedBy }, { data: sharedWith }] = await Promise.all([
api.partnerApi.getPartners({ direction: 'shared-by' }),
api.partnerApi.getPartners({ direction: 'shared-with' }),
const [sharedBy, sharedWith] = await Promise.all([
getPartners({ direction: 'shared-by' }),
getPartners({ direction: 'shared-with' }),
]);
for (const candidate of sharedBy) {
@ -69,13 +70,13 @@
};
const handleRemovePartner = async () => {
if (!removePartner) {
if (!removePartnerDto) {
return;
}
try {
await api.partnerApi.removePartner({ id: removePartner.id });
removePartner = null;
await removePartner({ id: removePartnerDto.id });
removePartnerDto = null;
await refreshPartners();
} catch (error) {
handleError(error, 'Unable to remove partner');
@ -85,11 +86,11 @@
const handleCreatePartners = async (users: UserResponseDto[]) => {
try {
for (const user of users) {
await api.partnerApi.createPartner({ id: user.id });
await createPartner({ id: user.id });
}
await refreshPartners();
createPartner = false;
createPartnerFlag = false;
} catch (error) {
handleError(error, 'Unable to add partners');
}
@ -97,7 +98,7 @@
const handleShowOnTimelineChanged = async (partner: PartnerSharing, inTimeline: boolean) => {
try {
await api.partnerApi.updatePartner({ id: partner.user.id, updatePartnerDto: { inTimeline } });
await updatePartner({ id: partner.user.id, updatePartnerDto: { inTimeline } });
partner.inTimeline = inTimeline;
partners = partners;
@ -126,7 +127,7 @@
{#if partner.sharedByMe}
<CircleIconButton
on:click={() => (removePartner = partner.user)}
on:click={() => (removePartnerDto = partner.user)}
icon={mdiClose}
size={'16'}
title="Stop sharing your photos with this user"
@ -167,23 +168,23 @@
{/if}
<div class="flex justify-end mt-5">
<Button size="sm" on:click={() => (createPartner = true)}>Add partner</Button>
<Button size="sm" on:click={() => (createPartnerFlag = true)}>Add partner</Button>
</div>
</section>
{#if createPartner}
{#if createPartnerFlag}
<PartnerSelectionModal
{user}
on:close={() => (createPartner = false)}
on:close={() => (createPartnerFlag = false)}
on:add-users={(event) => handleCreatePartners(event.detail)}
/>
{/if}
{#if removePartner}
{#if removePartnerDto}
<ConfirmDialogue
title="Stop sharing your photos?"
prompt="{removePartner.name} will no longer be able to access your photos."
on:cancel={() => (removePartner = null)}
prompt="{removePartnerDto.name} will no longer be able to access your photos."
on:cancel={() => (removePartnerDto = null)}
on:confirm={() => handleRemovePartner()}
/>
{/if}

View file

@ -1,15 +1,16 @@
<script lang="ts">
import { api, type APIKeyResponseDto } from '@api';
import Icon from '$lib/components/elements/icon.svelte';
import { locale } from '$lib/stores/preferences.store';
import { type APIKeyResponseDto } from '@api';
import { createApiKey, deleteApiKey, getApiKeys, updateApiKey } from '@immich/sdk';
import { mdiPencilOutline, mdiTrashCanOutline } from '@mdi/js';
import { fade } from 'svelte/transition';
import { handleError } from '../../utils/handle-error';
import Button from '../elements/buttons/button.svelte';
import APIKeyForm from '../forms/api-key-form.svelte';
import APIKeySecret from '../forms/api-key-secret.svelte';
import ConfirmDialogue from '../shared-components/confirm-dialogue.svelte';
import { notificationController, NotificationType } from '../shared-components/notification/notification';
import { locale } from '$lib/stores/preferences.store';
import Button from '../elements/buttons/button.svelte';
import { mdiPencilOutline, mdiTrashCanOutline } from '@mdi/js';
import { NotificationType, notificationController } from '../shared-components/notification/notification';
export let keys: APIKeyResponseDto[];
@ -25,13 +26,12 @@
};
async function refreshKeys() {
const { data } = await api.keyApi.getApiKeys();
keys = data;
keys = await getApiKeys();
}
const handleCreate = async (detail: Partial<APIKeyResponseDto>) => {
try {
const { data } = await api.keyApi.createApiKey({ aPIKeyCreateDto: detail });
const data = await createApiKey({ apiKeyCreateDto: detail });
secret = data.secret;
} catch (error) {
handleError(error, 'Unable to create a new API Key');
@ -47,7 +47,7 @@
}
try {
await api.keyApi.updateApiKey({ id: editKey.id, aPIKeyUpdateDto: { name: detail.name } });
await updateApiKey({ id: editKey.id, apiKeyUpdateDto: { name: detail.name } });
notificationController.show({
message: `Saved API Key`,
type: NotificationType.Info,
@ -66,7 +66,7 @@
}
try {
await api.keyApi.deleteApiKey({ id: deleteKey.id });
await deleteApiKey({ id: deleteKey.id });
notificationController.show({
message: `Removed API Key: ${deleteKey.name}`,
type: NotificationType.Info,

View file

@ -3,19 +3,19 @@
notificationController,
NotificationType,
} from '$lib/components/shared-components/notification/notification';
import { api } from '@api';
import { fade } from 'svelte/transition';
import { handleError } from '../../utils/handle-error';
import SettingInputField, { SettingInputFieldType } from '../admin-page/settings/setting-input-field.svelte';
import Button from '../elements/buttons/button.svelte';
import { user } from '$lib/stores/user.store';
import { cloneDeep } from 'lodash-es';
import { updateUser } from '@immich/sdk';
let editedUser = cloneDeep($user);
const handleSaveProfile = async () => {
try {
const { data } = await api.userApi.updateUser({
const data = await updateUser({
updateUserDto: {
id: editedUser.id,
email: editedUser.email,