mirror of
https://github.com/immich-app/immich
synced 2025-11-07 17:27:20 +00:00
feat(web): Add to Multiple Albums (#20072)
* Multi add to album picker: - update modal for multi select - Update add-to-album and add-to-album-action to work with new array return from AlbumPickerModal - Add asset-utils.addAssetsToAlbums (incomplete) * initial addToAlbums endpoint * - fix endpoint - add test * - update return type - make open-api * - simplify return dto - handle notification * - fix returns - clean up * - update i18n - format & check * - checks * - correct successId count - fix assets_cannot_be_added language call * tests * foromat * refactor * - update successful add message to included total attempted * - fix web test - format i18n * - fix open-api * - fix imports to resolve checks * - PR suggestions * open-api * refactor addAssetsToAlbums * refactor it again * - fix error returns and tests * - swap icon for IconButton - don't nest the buttons * open-api * - Cleanup multi-select button to match Thumbnail * merge and openapi * - remove onclick from icon element * - fix double onClose call with keyboard shortcuts * - spelling and formatting - apply new api permission * - open-api * chore: styling * translation --------- Co-authored-by: Alex <alex.tran1502@gmail.com>
This commit is contained in:
parent
e00556a34a
commit
9ff664ed36
24 changed files with 1280 additions and 55 deletions
|
|
@ -24,19 +24,26 @@ const createAlbumRow = (album: AlbumResponseDto, selected: boolean) => ({
|
|||
type: AlbumModalRowType.ALBUM_ITEM,
|
||||
album,
|
||||
selected,
|
||||
multiSelected: false,
|
||||
});
|
||||
|
||||
describe('Album Modal', () => {
|
||||
it('non-shared with no albums configured yet shows message and new', () => {
|
||||
const converter = new AlbumModalRowConverter(false, AlbumSortBy.MostRecentPhoto, SortOrder.Desc);
|
||||
const modalRows = converter.toModalRows('', [], [], -1);
|
||||
const modalRows = converter.toModalRows('', [], [], -1, []);
|
||||
|
||||
expect(modalRows).toStrictEqual([createNewAlbumRow(false), createMessageRow('no_albums_yet')]);
|
||||
});
|
||||
|
||||
it('non-shared with no matching albums shows message and new', () => {
|
||||
const converter = new AlbumModalRowConverter(false, AlbumSortBy.MostRecentPhoto, SortOrder.Desc);
|
||||
const modalRows = converter.toModalRows('matches_nothing', [], [albumFactory.build({ albumName: 'Holidays' })], -1);
|
||||
const modalRows = converter.toModalRows(
|
||||
'matches_nothing',
|
||||
[],
|
||||
[albumFactory.build({ albumName: 'Holidays' })],
|
||||
-1,
|
||||
[],
|
||||
);
|
||||
|
||||
expect(modalRows).toStrictEqual([createNewAlbumRow(false), createMessageRow('no_albums_with_name_yet')]);
|
||||
});
|
||||
|
|
@ -44,7 +51,7 @@ describe('Album Modal', () => {
|
|||
it('non-shared displays single albums', () => {
|
||||
const converter = new AlbumModalRowConverter(false, AlbumSortBy.MostRecentPhoto, SortOrder.Desc);
|
||||
const holidayAlbum = albumFactory.build({ albumName: 'Holidays' });
|
||||
const modalRows = converter.toModalRows('', [], [holidayAlbum], -1);
|
||||
const modalRows = converter.toModalRows('', [], [holidayAlbum], -1, []);
|
||||
|
||||
expect(modalRows).toStrictEqual([
|
||||
createNewAlbumRow(false),
|
||||
|
|
@ -64,6 +71,7 @@ describe('Album Modal', () => {
|
|||
[holidayAlbum, constructionAlbum],
|
||||
[holidayAlbum, constructionAlbum, birthdayAlbum, christmasAlbum],
|
||||
-1,
|
||||
[],
|
||||
);
|
||||
|
||||
expect(modalRows).toStrictEqual([
|
||||
|
|
@ -90,6 +98,7 @@ describe('Album Modal', () => {
|
|||
[holidayAlbum, constructionAlbum],
|
||||
[holidayAlbum, constructionAlbum, birthdayAlbum, christmasAlbum],
|
||||
-1,
|
||||
[],
|
||||
);
|
||||
|
||||
expect(modalRows).toStrictEqual([
|
||||
|
|
@ -112,6 +121,7 @@ describe('Album Modal', () => {
|
|||
[holidayAlbum, constructionAlbum],
|
||||
[holidayAlbum, constructionAlbum, birthdayAlbum, christmasAlbum],
|
||||
-1,
|
||||
[],
|
||||
);
|
||||
|
||||
expect(modalRows).toStrictEqual([
|
||||
|
|
@ -125,7 +135,7 @@ describe('Album Modal', () => {
|
|||
const converter = new AlbumModalRowConverter(false, AlbumSortBy.MostRecentPhoto, SortOrder.Desc);
|
||||
const holidayAlbum = albumFactory.build({ albumName: 'Holidays' });
|
||||
const constructionAlbum = albumFactory.build({ albumName: 'Construction' });
|
||||
const modalRows = converter.toModalRows('', [holidayAlbum], [holidayAlbum, constructionAlbum], 0);
|
||||
const modalRows = converter.toModalRows('', [holidayAlbum], [holidayAlbum, constructionAlbum], 0, []);
|
||||
|
||||
expect(modalRows).toStrictEqual([
|
||||
createNewAlbumRow(true),
|
||||
|
|
@ -141,7 +151,7 @@ describe('Album Modal', () => {
|
|||
const converter = new AlbumModalRowConverter(false, AlbumSortBy.MostRecentPhoto, SortOrder.Desc);
|
||||
const holidayAlbum = albumFactory.build({ albumName: 'Holidays' });
|
||||
const constructionAlbum = albumFactory.build({ albumName: 'Construction' });
|
||||
const modalRows = converter.toModalRows('', [holidayAlbum], [holidayAlbum, constructionAlbum], 1);
|
||||
const modalRows = converter.toModalRows('', [holidayAlbum], [holidayAlbum, constructionAlbum], 1, []);
|
||||
|
||||
expect(modalRows).toStrictEqual([
|
||||
createNewAlbumRow(false),
|
||||
|
|
@ -157,7 +167,7 @@ describe('Album Modal', () => {
|
|||
const converter = new AlbumModalRowConverter(false, AlbumSortBy.MostRecentPhoto, SortOrder.Desc);
|
||||
const holidayAlbum = albumFactory.build({ albumName: 'Holidays' });
|
||||
const constructionAlbum = albumFactory.build({ albumName: 'Construction' });
|
||||
const modalRows = converter.toModalRows('', [holidayAlbum], [holidayAlbum, constructionAlbum], 3);
|
||||
const modalRows = converter.toModalRows('', [holidayAlbum], [holidayAlbum, constructionAlbum], 3, []);
|
||||
|
||||
expect(modalRows).toStrictEqual([
|
||||
createNewAlbumRow(false),
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ export enum AlbumModalRowType {
|
|||
export type AlbumModalRow = {
|
||||
type: AlbumModalRowType;
|
||||
selected?: boolean;
|
||||
multiSelected?: boolean;
|
||||
text?: string;
|
||||
album?: AlbumResponseDto;
|
||||
};
|
||||
|
|
@ -41,6 +42,7 @@ export class AlbumModalRowConverter {
|
|||
recentAlbums: AlbumResponseDto[],
|
||||
albums: AlbumResponseDto[],
|
||||
selectedRowIndex: number,
|
||||
multiSelectedAlbumIds: string[],
|
||||
): AlbumModalRow[] {
|
||||
// only show recent albums if no search was entered, or we're in the normal albums (non-shared) modal.
|
||||
const recentAlbumsToShow = !this.shared && search.length === 0 ? recentAlbums : [];
|
||||
|
|
@ -64,6 +66,7 @@ export class AlbumModalRowConverter {
|
|||
rows.push({
|
||||
type: AlbumModalRowType.ALBUM_ITEM,
|
||||
selected: selectedRowIndex === i + selectedOffsetDueToNewAlbumRow,
|
||||
multiSelected: multiSelectedAlbumIds.includes(album.id),
|
||||
album,
|
||||
});
|
||||
}
|
||||
|
|
@ -81,6 +84,7 @@ export class AlbumModalRowConverter {
|
|||
rows.push({
|
||||
type: AlbumModalRowType.ALBUM_ITEM,
|
||||
selected: selectedRowIndex === i + selectedOffsetDueToNewAndRecents,
|
||||
multiSelected: multiSelectedAlbumIds.includes(album.id),
|
||||
album,
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
<script lang="ts">
|
||||
import type { Action } from 'svelte/action';
|
||||
import { mdiPlus } from '@mdi/js';
|
||||
import { t } from 'svelte-i18n';
|
||||
import Icon from '$lib/components/elements/icon.svelte';
|
||||
import { SCROLL_PROPERTIES } from '$lib/components/shared-components/album-selection/album-selection-utils';
|
||||
import { mdiPlus } from '@mdi/js';
|
||||
import { t } from 'svelte-i18n';
|
||||
import type { Action } from 'svelte/action';
|
||||
|
||||
interface Props {
|
||||
searchQuery?: string;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue