Add SelectedTagBadge to offer context items for selected tags

This commit is contained in:
Henrik Giesel 2021-06-29 22:41:43 +02:00
parent 00de99880b
commit 874a315f83
5 changed files with 107 additions and 3 deletions

View file

@ -53,7 +53,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
/* Set custom menu without using common element with .dropdown */
(dropdown as any)._menu = menu;
Object.defineProperty(dropdown, "isVisible", { value: isVisible });
return dropdown as Dropdown;
}
</script>

View file

@ -134,6 +134,7 @@ copy_mdi_icons(
"tag-outline.svg",
"tag.svg",
"tag-plus.svg",
"dots-vertical.svg",
],
visibility = ["//visibility:public"],
)

View file

@ -0,0 +1,64 @@
<!--
Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
-->
<script lang="ts">
import { createEventDispatcher } from "svelte";
import Badge from "components/Badge.svelte";
import WithDropdownMenu from "components/WithDropdownMenu.svelte";
import WithShortcut from "components/WithShortcut.svelte";
import DropdownMenu from "components/DropdownMenu.svelte";
import DropdownItem from "components/DropdownItem.svelte";
import { withSpan, withButton } from "components/helpers";
import { appendInParentheses } from "./helpers";
import { dotsIcon } from "./icons";
const dispatch = createEventDispatcher();
const copyLabel = "Copy tags";
const removeLabel = "Remove tags";
</script>
<WithDropdownMenu let:menuId let:createDropdown>
<div class="dropdown">
<div class="more-icon">
<Badge class="me-1" on:mount={withSpan(createDropdown)}
>{@html dotsIcon}</Badge
>
</div>
<DropdownMenu id={menuId}>
<WithShortcut shortcut="C" let:createShortcut let:shortcutLabel>
<DropdownItem
on:click={() => dispatch("tagcopy")}
on:mount={withButton(createShortcut)}
>{appendInParentheses(copyLabel, shortcutLabel)}</DropdownItem
>
</WithShortcut>
<WithShortcut shortcut="Backspace" let:createShortcut let:shortcutLabel>
<DropdownItem
on:click={() => dispatch("tagdelete")}
on:mount={withButton(createShortcut)}
>{appendInParentheses(removeLabel, shortcutLabel)}</DropdownItem
>
</WithShortcut>
</DropdownMenu>
</div>
</WithDropdownMenu>
<style lang="scss">
.more-icon {
line-height: 1;
:global(svg) {
cursor: pointer;
fill: currentColor;
opacity: 0.6;
}
:global(svg:hover) {
opacity: 1;
}
}
</style>

View file

@ -8,6 +8,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import { bridgeCommand } from "lib/bridgecommand";
import StickyBottom from "components/StickyBottom.svelte";
import AddTagBadge from "./AddTagBadge.svelte";
import SelectedTagBadge from "./SelectedTagBadge.svelte";
import Tag from "./Tag.svelte";
import TagInput from "./TagInput.svelte";
import WithAutocomplete from "./WithAutocomplete.svelte";
@ -322,6 +323,37 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
deselect();
}
}
/* TODO replace with navigator.clipboard once available */
function copyToClipboard(content: string): void {
const textarea = document.createElement("textarea");
textarea.value = content;
textarea.setAttribute("readonly", "");
textarea.style.position = "absolute";
textarea.style.left = "-9999px";
document.body.appendChild(textarea);
textarea.select();
document.execCommand("copy");
document.body.removeChild(textarea);
}
function copySelectedTags() {
const content = tags
.filter((tag) => tag.selected)
.map((tag) => tag.name)
.join("\n");
copyToClipboard(content);
deselect();
}
function deleteSelectedTags() {
tags.map((tag, index) => [tag.selected, index])
.filter(([selected]) => selected)
.reverse()
.forEach(([, index]) => deleteTagAt(index as number));
deselect();
saveTags();
}
</script>
<StickyBottom>
@ -330,8 +362,15 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
{size}
on:focusout={deselectIfLeave}
>
<div class="pb-1">
<AddTagBadge on:click={appendEmptyTag} />
<div class="pb-1" on:mousedown|preventDefault>
{#if tags.some((tag) => tag.selected)}
<SelectedTagBadge
on:tagcopy={copySelectedTags}
on:tagdelete={deleteSelectedTags}
/>
{:else}
<AddTagBadge on:click={appendEmptyTag} />
{/if}
</div>
{#each tags as tag, index (tag.id)}

View file

@ -33,6 +33,7 @@ export { default as xmlIcon } from "./xml.svg";
export { default as tagIcon } from "./tag.svg";
export { default as addTagIcon } from "./tag-plus.svg";
export { default as dotsIcon } from "./dots-vertical.svg";
export { default as deleteIcon } from "./x.svg";
export const arrowIcon =