feat: tags ()

* feat: tags

* fix: folder tree icons

* navigate to tag from detail panel

* delete tag

* Tag position and add tag button

* Tag asset in detail panel

* refactor form

* feat: navigate to tag page from clicking on a tag

* feat: delete tags from the tag page

* refactor: moving tag section in detail panel and add + tag button

* feat: tag asset action in detail panel

* refactor add tag form

* fdisable add tag button when there is no selection

* feat: tag bulk endpoint

* feat: tag colors

* chore: clean up

* chore: unit tests

* feat: write tags to sidecar

* Remove tag and auto focus on tag creation form opened

* chore: regenerate migration

* chore: linting

* add color picker to tag edit form

* fix: force render tags timeline on navigating back from asset viewer

* feat: read tags from keywords

* chore: clean up

---------

Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
This commit is contained in:
Jason Rasmussen 2024-08-29 12:14:03 -04:00 committed by GitHub
parent 682adaa334
commit d08a20bd57
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
68 changed files with 3032 additions and 814 deletions
web/src/lib/utils

View file

@ -10,6 +10,7 @@ import { preferences } from '$lib/stores/user.store';
import { downloadRequest, getKey, withError } from '$lib/utils';
import { createAlbum } from '$lib/utils/album-utils';
import { getByteUnitString } from '$lib/utils/byte-units';
import { getFormatter } from '$lib/utils/i18n';
import {
addAssetsToAlbum as addAssets,
createStack,
@ -18,6 +19,8 @@ import {
getBaseUrl,
getDownloadInfo,
getStack,
tagAssets as tagAllAssets,
untagAssets,
updateAsset,
updateAssets,
type AlbumResponseDto,
@ -61,6 +64,54 @@ export const addAssetsToAlbum = async (albumId: string, assetIds: string[], show
}
};
export const tagAssets = async ({
assetIds,
tagIds,
showNotification = true,
}: {
assetIds: string[];
tagIds: string[];
showNotification?: boolean;
}) => {
for (const tagId of tagIds) {
await tagAllAssets({ id: tagId, bulkIdsDto: { ids: assetIds } });
}
if (showNotification) {
const $t = await getFormatter();
notificationController.show({
message: $t('tagged_assets', { values: { count: assetIds.length } }),
type: NotificationType.Info,
});
}
return assetIds;
};
export const removeTag = async ({
assetIds,
tagIds,
showNotification = true,
}: {
assetIds: string[];
tagIds: string[];
showNotification?: boolean;
}) => {
for (const tagId of tagIds) {
await untagAssets({ id: tagId, bulkIdsDto: { ids: assetIds } });
}
if (showNotification) {
const $t = await getFormatter();
notificationController.show({
message: $t('removed_tagged_assets', { values: { count: assetIds.length } }),
type: NotificationType.Info,
});
}
return assetIds;
};
export const addAssetsToNewAlbum = async (albumName: string, assetIds: string[]) => {
const album = await createAlbum(albumName, assetIds);
if (!album) {