Files
immich/web/src/lib/components/user-settings-page/partner-settings.svelte
Manic-87 f446bc8caa feat(web): translations (#9854)
* First test

* Added translation using Weblate (French)

* Translated using Weblate (German)

Currently translated at 100.0% (4 of 4 strings)

Translation: immich/web
Translate-URL: http://familie-mach.net/projects/immich/web/de/

* Translated using Weblate (French)

Currently translated at 100.0% (4 of 4 strings)

Translation: immich/web
Translate-URL: http://familie-mach.net/projects/immich/web/fr/

* Further testing

* Further testing

* Translated using Weblate (German)

Currently translated at 100.0% (18 of 18 strings)

Translation: immich/web
Translate-URL: http://familie-mach.net/projects/immich/web/de/

* Further work

* Update string file.

* More strings

* Automatically changed strings

* Add automatically translated german file for testing purposes

* Fix merge-face-selector component

* Make server stats strings uppercase

* Fix uppercase string

* Fix some strings in jobs-panel

* Fix lower and uppercase strings. Add a few additional string. Fix a few unnecessary replacements

* Update german test translations

* Fix typo in locales file

* Change string keys

* Extract more strings

* Extract and replace some more strings

* Update testtranslationfile

* Change translation keys

* Fix rebase errors

* Fix one more rebase error

* Remove german translation file

* Co-authored-by: Daniel Dietzler <danieldietzler@users.noreply.github.com>

* chore: clean up translations

* chore: add new line

* fix formatting

* chore: fixes

* fix: loading and tests

---------

Co-authored-by: root <root@Blacki>
Co-authored-by: admin <admin@example.com>
Co-authored-by: Jason Rasmussen <jrasm91@gmail.com>
Co-authored-by: Daniel Dietzler <mail@ddietzler.dev>
2024-06-04 15:53:00 -04:00

194 lines
6.1 KiB
Svelte

<script lang="ts">
import {
createPartner,
getPartners,
removePartner,
updatePartner,
type PartnerResponseDto,
type UserResponseDto,
} from '@immich/sdk';
import { mdiCheck, mdiClose } from '@mdi/js';
import { onMount } from 'svelte';
import { handleError } from '../../utils/handle-error';
import Button from '../elements/buttons/button.svelte';
import CircleIconButton from '../elements/buttons/circle-icon-button.svelte';
import Icon from '../elements/icon.svelte';
import UserAvatar from '$lib/components/shared-components/user-avatar.svelte';
import PartnerSelectionModal from './partner-selection-modal.svelte';
import SettingSwitch from '$lib/components/shared-components/settings/setting-switch.svelte';
import { dialogController } from '$lib/components/shared-components/dialog/dialog';
import { t } from 'svelte-i18n';
interface PartnerSharing {
user: UserResponseDto;
sharedByMe: boolean;
sharedWithMe: boolean;
inTimeline: boolean;
}
export let user: UserResponseDto;
let createPartnerFlag = false;
// let removePartnerDto: PartnerResponseDto | null = null;
let partners: Array<PartnerSharing> = [];
onMount(async () => {
await refreshPartners();
});
const refreshPartners = async () => {
partners = [];
const [sharedBy, sharedWith] = await Promise.all([
getPartners({ direction: 'shared-by' }),
getPartners({ direction: 'shared-with' }),
]);
for (const candidate of sharedBy) {
partners = [
...partners,
{
user: candidate,
sharedByMe: true,
sharedWithMe: false,
inTimeline: candidate.inTimeline ?? false,
},
];
}
for (const candidate of sharedWith) {
const existIndex = partners.findIndex((p) => candidate.id === p.user.id);
if (existIndex >= 0) {
partners[existIndex].sharedWithMe = true;
partners[existIndex].inTimeline = candidate.inTimeline ?? false;
} else {
partners = [
...partners,
{
user: candidate,
sharedByMe: false,
sharedWithMe: true,
inTimeline: candidate.inTimeline ?? false,
},
];
}
}
};
const handleRemovePartner = async (partner: PartnerResponseDto) => {
const isConfirmed = await dialogController.show({
id: 'remove-partner',
title: 'Stop sharing your photos?',
prompt: `${partner.name} will no longer be able to access your photos.`,
});
if (!isConfirmed) {
return;
}
try {
await removePartner({ id: partner.id });
await refreshPartners();
} catch (error) {
handleError(error, $t('errors.unable_to_remove_partner'));
}
};
const handleCreatePartners = async (users: UserResponseDto[]) => {
try {
for (const user of users) {
await createPartner({ id: user.id });
}
await refreshPartners();
createPartnerFlag = false;
} catch (error) {
handleError(error, $t('errors.unable_to_add_partners'));
}
};
const handleShowOnTimelineChanged = async (partner: PartnerSharing, inTimeline: boolean) => {
try {
await updatePartner({ id: partner.user.id, updatePartnerDto: { inTimeline } });
partner.inTimeline = inTimeline;
partners = partners;
} catch (error) {
handleError(error, 'Unable to update timeline display status');
}
};
</script>
<section class="my-4">
{#if partners.length > 0}
{#each partners as partner (partner.user.id)}
<div class="rounded-2xl border border-gray-200 dark:border-gray-800 mt-6 bg-slate-50 dark:bg-gray-900 p-5">
<div class="flex gap-4 rounded-lg pb-4 transition-all justify-between">
<div class="flex gap-4">
<UserAvatar user={partner.user} size="md" />
<div class="text-left">
<p class="text-immich-fg dark:text-immich-dark-fg">
{partner.user.name}
</p>
<p class="text-sm text-immich-fg/75 dark:text-immich-dark-fg/75">
{partner.user.email}
</p>
</div>
</div>
{#if partner.sharedByMe}
<CircleIconButton
on:click={() => handleRemovePartner(partner.user)}
icon={mdiClose}
size={'16'}
title="Stop sharing your photos with this user"
/>
{/if}
</div>
<div class="dark:text-gray-200 text-immich-dark-gray">
<!-- I am sharing my assets with this user -->
{#if partner.sharedByMe}
<hr class="my-4 border border-gray-200 dark:border-gray-700" />
<p class="text-xs font-medium my-4">SHARED WITH {partner.user.name.toUpperCase()}</p>
<p class="text-md">{partner.user.name} can access</p>
<ul class="text-sm">
<li class="flex gap-2 place-items-center py-1 mt-2">
<Icon path={mdiCheck} /> All your photos and videos except those in Archived and Deleted
</li>
<li class="flex gap-2 place-items-center py-1">
<Icon path={mdiCheck} /> The location where your photos were taken
</li>
</ul>
{/if}
<!-- this user is sharing assets with me -->
{#if partner.sharedWithMe}
<hr class="my-4 border border-gray-200 dark:border-gray-700" />
<p class="text-xs font-medium my-4">PHOTOS FROM {partner.user.name.toUpperCase()}</p>
<SettingSwitch
title={$t('show_in_timeline')}
subtitle={$t('show_in_timeline_setting_description')}
bind:checked={partner.inTimeline}
on:toggle={({ detail }) => handleShowOnTimelineChanged(partner, detail)}
/>
{/if}
</div>
</div>
{/each}
{/if}
<div class="flex justify-end mt-5">
<Button size="sm" on:click={() => (createPartnerFlag = true)}>{$t('add_partner')}</Button>
</div>
</section>
{#if createPartnerFlag}
<PartnerSelectionModal
{user}
onClose={() => (createPartnerFlag = false)}
on:add-users={(event) => handleCreatePartners(event.detail)}
/>
{/if}