Skip to content
Merged

Dev #74

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion resources/style/controls/popover.scss
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ dialog[role='alertdialog'] {
}
}

#tag-remove-overview {
.tag-overview {
overflow-y: auto;
max-height: 300px;
}
2 changes: 1 addition & 1 deletion src/frontend/components/RemovalAlert.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export const TagRemoval = observer((props: IRemovalProps<ClientTag>) => {
information="Deleting tags or collections will permanently remove them from Allusion."
body={
tagsToRemove.length > 0 && (
<div id="tag-remove-overview">
<div id="tag-remove-overview" className="tag-overview">
<p>Selected Tags</p>
{tagsToRemove}
</div>
Expand Down
26 changes: 25 additions & 1 deletion src/frontend/containers/ContentView/menu-items.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,7 @@ export const ExternalAppMenuItems = observer(({ file }: { file: ClientFile }) =>

export const FileTagMenuItems = observer(({ file, tag }: { file?: ClientFile; tag: ClientTag }) => {
const { uiStore } = useStore();
const ctxTags = uiStore.getTagContextItems(tag.id);
return (
<>
<MenuItem
Expand All @@ -321,9 +322,20 @@ export const FileTagMenuItems = observer(({ file, tag }: { file?: ClientFile; ta
text="Edit Tag"
icon={IconSet.EDIT}
/>
<MenuItem
onClick={() => uiStore.openTagMovePanel(tag)}
text="Move Tag To"
icon={IconSet.TAG_GROUP}
/>
<MenuItem
onClick={() => uiStore.openTagMergePanel(tag)}
text="Merge Tag With"
icon={IconSet.TAG_GROUP}
disabled={ctxTags.some((tag) => tag.subTags.length > 0)}
/>
<MenuItem
onClick={() => file && file.removeTag(tag)}
text="Unassign Tag from File"
text="Unassign Tag From File"
icon={IconSet.TAG_BLANCO}
/>
</>
Expand All @@ -338,6 +350,7 @@ export const EditorTagSummaryItems = ({
beforeSelect: () => void;
}) => {
const { uiStore } = useStore();
const ctxTags = uiStore.getTagContextItems(tag.id);
return (
<>
<MenuItem
Expand All @@ -356,6 +369,17 @@ export const EditorTagSummaryItems = ({
text="Edit Tag"
icon={IconSet.EDIT}
/>
<MenuItem
onClick={() => uiStore.openTagMovePanel(tag)}
text="Move To"
icon={IconSet.TAG_GROUP}
/>
<MenuItem
onClick={() => uiStore.openTagMergePanel(tag)}
text="Merge With"
icon={IconSet.TAG_GROUP}
disabled={ctxTags.some((tag) => tag.subTags.length > 0)}
/>
</>
);
};
Expand Down
6 changes: 3 additions & 3 deletions src/frontend/containers/Outliner/TagsPanel/ContextMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,8 @@ export const TagItemContextMenu = observer((props: IContextMenuProps) => {
onClick={tag.toggleHidden}
/>
<MenuItem
onClick={() => dispatch(Factory.confirmMerge(tag))}
text="Merge with"
onClick={() => uiStore.openTagMergePanel(tag)}
text="Merge With"
icon={IconSet.TAG_GROUP}
disabled={ctxTags.some((tag) => tag.subTags.length > 0)}
/>
Expand Down Expand Up @@ -186,7 +186,7 @@ export const TagItemContextMenu = observer((props: IContextMenuProps) => {
disabled={pos === tag.parent.subTags.length}
/>
<MenuItem
onClick={() => dispatch(Factory.confirmMove(tag))}
onClick={() => uiStore.openTagMovePanel(tag)}
text="Move To"
icon={IconSet.TAG_GROUP}
/>
Expand Down
40 changes: 23 additions & 17 deletions src/frontend/containers/Outliner/TagsPanel/TagMerge.tsx
Original file line number Diff line number Diff line change
@@ -1,37 +1,37 @@
import { observer } from 'mobx-react-lite';
import React, { useEffect, useState } from 'react';

import { Button, Checkbox, IconSet, Tag } from 'widgets';
import { Button, IconSet, Tag } from 'widgets';
import { Dialog } from 'widgets/popovers';
import { useStore } from '../../../contexts/StoreContext';
import { ClientTag } from '../../../entities/Tag';
import { Placement } from '@floating-ui/core';
import { TagSelector } from 'src/frontend/components/TagSelector';
import { Menu, MenuCheckboxItem } from 'widgets/menus';

interface TagMergeProps {
tag: ClientTag;
onClose: () => void;
}
import { MenuCheckboxItem } from 'widgets/menus';

const ADD_AS_ALIAS_ID = 'merge-add-as-alias';
const FALLBACK_PLACEMENTS: Placement[] = ['bottom'];

/** this component is only shown when all tags in the context do not have child-tags */
export const TagMerge = observer(({ tag, onClose }: TagMergeProps) => {
export const TagMerge = observer(() => {
const { tagStore, uiStore } = useStore();
const [selectedTag, setSelectedTag] = useState<ClientTag>();
const [addAsAliasEnabled, setAddAsAlias] = useState(
localStorage.getItem(ADD_AS_ALIAS_ID) == 'true',
);

const tag = uiStore.tagToMerge;
const isOpen = tag !== undefined;
const ctxTags = uiStore.getTagContextItems(tag?.id);

const onClose = () => {
uiStore.closeTagMergePanel();
};

useEffect(() => {
localStorage.setItem(ADD_AS_ALIAS_ID, JSON.stringify(addAsAliasEnabled));
}, [addAsAliasEnabled]);

const ctxTags = uiStore.getTagContextItems(tag.id);

const [selectedTag, setSelectedTag] = useState<ClientTag>();

const mergingWithSelf = ctxTags.some((t) => t.id === selectedTag?.id);

const merge = () => {
Expand All @@ -45,9 +45,13 @@ export const TagMerge = observer(({ tag, onClose }: TagMergeProps) => {

const plur = ctxTags.length === 1 ? '' : 's';

if (!isOpen) {
return null;
}

return (
<Dialog
open
open={isOpen}
title={`Merge Tag${plur} With`}
icon={IconSet.TAG_GROUP}
onCancel={onClose}
Expand All @@ -61,9 +65,11 @@ export const TagMerge = observer(({ tag, onClose }: TagMergeProps) => {
<div id="tag-merge-overview">
<label className="dialog-label">Tag{plur} to merge:</label>
<br />
{ctxTags.map((tag) => (
<Tag key={tag.id} text={tag.name} color={tag.viewColor} isHeader={tag.isHeader} />
))}
<div className="tag-overview">
{ctxTags.map((tag) => (
<Tag key={tag.id} text={tag.name} color={tag.viewColor} isHeader={tag.isHeader} />
))}
</div>
</div>

<br />
Expand All @@ -75,7 +81,7 @@ export const TagMerge = observer(({ tag, onClose }: TagMergeProps) => {
<br />

<label className="dialog-label" htmlFor="tag-merge-picker">
Merge with
Merge With
</label>
<TagSelector
fallbackPlacements={FALLBACK_PLACEMENTS}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'

import { Button, IconSet, Tag } from 'widgets';
import { Dialog } from 'widgets/popovers';
import { ClientTag } from '../../entities/Tag';
import { ClientTag } from '../../../entities/Tag';
import { TagSelector } from 'src/frontend/components/TagSelector';
import { Placement } from '@floating-ui/core';
import { computed } from 'mobx';
import { InfoButton } from 'widgets/notifications';
import { ColorPickerMenu, TagVisibilityMenu } from './TagsPanel/ContextMenu';
import { ColorPickerMenu, TagVisibilityMenu } from './ContextMenu';
import { Menu, MenuCheckboxItem } from 'widgets/menus';
import { useStore } from 'src/frontend/contexts/StoreContext';

Expand Down
31 changes: 19 additions & 12 deletions src/frontend/containers/Outliner/TagsPanel/TagsMoveTo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,22 @@ import { TagSelector } from 'src/frontend/components/TagSelector';
import { Placement } from '@floating-ui/core';
import { AppToaster } from 'src/frontend/components/Toaster';

interface TagMoveToProps {
tag: ClientTag;
onClose: () => void;
}

const FALLBACK_PLACEMENTS: Placement[] = ['bottom'];

export const TagsMoveTo = observer(({ tag, onClose }: TagMoveToProps) => {
export const TagsMoveTo = observer(() => {
const { uiStore } = useStore();
const [selectedTag, setSelectedTag] = useState<ClientTag>();

const ctxTags = uiStore.getTagContextItems(tag.id);
const tag = uiStore.tagToMove;
const ctxTags = uiStore.getTagContextItems(tag?.id);
const isOpen = tag !== undefined;
const isMulti = ctxTags.length > 1;
const plur = isMulti ? 's' : '';

const onClose = () => {
uiStore.closeTagMovePanel();
};

const handleMove = () => {
let count = 0;
if (selectedTag !== undefined) {
Expand All @@ -47,9 +48,13 @@ export const TagsMoveTo = observer(({ tag, onClose }: TagMoveToProps) => {
onClose();
};

if (!isOpen) {
return null;
}

return (
<Dialog
open
open={isOpen}
title={`Move Tag${plur} Into Another Tag`}
icon={IconSet.TAG_GROUP}
onCancel={onClose}
Expand All @@ -66,15 +71,17 @@ export const TagsMoveTo = observer(({ tag, onClose }: TagMoveToProps) => {
<div id="tag-move-overview">
<label className="dialog-label">Tag{plur} to move:</label>
<br />
{ctxTags.map((tag) => (
<Tag key={tag.id} text={tag.name} color={tag.viewColor} isHeader={tag.isHeader} />
))}
<div className="tag-overview">
{ctxTags.map((tag) => (
<Tag key={tag.id} text={tag.name} color={tag.viewColor} isHeader={tag.isHeader} />
))}
</div>
</div>

<br />

<label className="dialog-label" htmlFor="tag-move-picker">
Move to
Move To
</label>
<TagSelector
fallbackPlacements={FALLBACK_PLACEMENTS}
Expand Down
12 changes: 0 additions & 12 deletions src/frontend/containers/Outliner/TagsPanel/TagsTree.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import {
} from 'widgets/tree';
import { ROOT_TAG_ID } from '../../../../api/tag';
import { TagRemoval } from '../../../components/RemovalAlert';
import { TagMerge } from '../../../containers/Outliner/TagsPanel/TagMerge';
import { useStore } from '../../../contexts/StoreContext';
import { DnDTagType, useTagDnD } from '../../../contexts/TagDnDContext';
import { ClientTagSearchCriteria } from '../../../entities/SearchCriteria';
Expand All @@ -33,7 +32,6 @@ import { TagItemContextMenu } from './ContextMenu';
import SearchButton from './SearchButton';
import { Action, Factory, Flag, State, reducer } from './state';
import { ID } from 'src/api/id';
import { TagsMoveTo } from './TagsMoveTo';

export class TagsTreeItemRevealer extends TreeItemRevealer {
public static readonly instance: TagsTreeItemRevealer = new TagsTreeItemRevealer();
Expand Down Expand Up @@ -564,8 +562,6 @@ const TagsTree = observer((props: Partial<MultiSplitPaneProps>) => {
expansion: {},
editableNode: undefined,
deletableNode: undefined,
mergableNode: undefined,
movableNode: undefined,
});
const dndData = useTagDnD();
const vTreeRef = useRef<VirtualizedTreeHandle>(null);
Expand Down Expand Up @@ -859,14 +855,6 @@ const TagsTree = observer((props: Partial<MultiSplitPaneProps>) => {
onClose={() => dispatch(Factory.abortDeletion())}
/>
)}

{state.mergableNode && (
<TagMerge tag={state.mergableNode} onClose={() => dispatch(Factory.abortMerge())} />
)}

{state.movableNode && (
<TagsMoveTo tag={state.movableNode} onClose={() => dispatch(Factory.abortMove())} />
)}
</MultiSplitPane>
);
});
Expand Down
12 changes: 11 additions & 1 deletion src/frontend/containers/Outliner/TagsPanel/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import { ClientTagSearchCriteria } from '../../../entities/SearchCriteria';
import { useAction } from '../../../hooks/mobx';
import { comboMatches, getKeyCombo, parseKeyCombo } from '../../../hotkeyParser';
import TagsTree from './TagsTree';
import { TagPropertiesEditor } from './TagPropertiesEditor';
import { TagsMoveTo } from './TagsMoveTo';
import { TagMerge } from './TagMerge';

// Tooltip info
const enum TooltipInfo {
Expand Down Expand Up @@ -86,7 +89,14 @@ const TagsPanel = (props: Partial<MultiSplitPaneProps>) => {
}
});

return <TagsTree onKeyDown={handleShortcuts} {...props} />;
return (
<>
<TagsTree onKeyDown={handleShortcuts} {...props} />
<TagPropertiesEditor />
<TagMerge />
<TagsMoveTo />
</>
);
};

export default TagsPanel;
Loading
Loading