Skip to content

Commit

Permalink
feat(138): update tag selector fallback text
Browse files Browse the repository at this point in the history
  • Loading branch information
nathanielrindlaub committed Dec 2, 2024
1 parent ffcccdf commit 8d5799a
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 61 deletions.
62 changes: 30 additions & 32 deletions src/components/TagSelector.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@ import { styled } from '../theme/stitches.config.js';
// [FUTURE FEATURE]
// import { Cross2Icon, MagnifyingGlassIcon } from '@radix-ui/react-icons';
import { PlusCircledIcon } from '@radix-ui/react-icons';
import { Root as PopoverRoot, PopoverTrigger, PopoverContent, PopoverPortal } from '@radix-ui/react-popover';
import {
Root as PopoverRoot,
PopoverTrigger,
PopoverContent,
PopoverPortal,
} from '@radix-ui/react-popover';
import { mauve, violet } from '@radix-ui/colors';

const Selector = styled('div', {
Expand All @@ -20,13 +25,13 @@ const Selector = styled('div', {
borderWidth: '1px',
'&:hover': {
cursor: 'pointer',
background: violet.violet3
}
background: violet.violet3,
},
});

const SelectorTitle = styled('div', {
display: 'flex',
gap: '$2'
gap: '$2',
});

const TagSelectorContent = styled('div', {
Expand Down Expand Up @@ -69,20 +74,20 @@ const TagSelectorContent = styled('div', {
const TagOptionsContainer = styled('div', {
maxHeight: '50vh',
overflowY: 'auto',
maxWidth: 450
maxWidth: 450,
});

const TagOption = styled('div', {
padding: '$1 $3',
'&:hover': {
background: '$gray3',
cursor: 'pointer',
}
},
});

const AllTagsAdded = styled('div', {
const DefaultTagMessage = styled('div', {
padding: '$2 $3',
color: '$gray10'
color: '$gray10',
});

// [FUTURE FEATURE]
Expand All @@ -97,15 +102,12 @@ const AllTagsAdded = styled('div', {
// const allTagsAdded = "All tags added"
// const noMatches = "No matches"

export const TagSelector = ({
tagList,
onAddTag,
imageId,
}) => {
export const TagSelector = ({ projectTags, unaddedTags, onAddTag, imageId }) => {
const [isOpen, setIsOpen] = useState(false);
const [tagOptions, setTagOptions] = useState(tagList);
const errMessage = "All tags added";
const [tagOptions, setTagOptions] = useState(unaddedTags);

// [FUTURE FEATURE]
// const errMessage = 'All tags added';
// const [searchValue, setSearchValue] = useState("");
// const [errMessage, setErrMessage] = useState(allTagsAdded);

Expand Down Expand Up @@ -133,10 +135,10 @@ export const TagSelector = ({
// }

const onClickTag = (tag) => {
const options = tagOptions.filter(({ _id }) => _id !== tag._id );
const options = tagOptions.filter(({ _id }) => _id !== tag._id);
setTagOptions(options);
onAddTag(tag);
}
};

// Close when changing image using keyboard nav
useEffect(() => {
Expand All @@ -145,29 +147,25 @@ export const TagSelector = ({

return (
<PopoverRoot open={isOpen} onOpenChange={setIsOpen}>
<PopoverTrigger asChild onClick={() => setTagOptions(tagList)}>
<PopoverTrigger asChild onClick={() => setTagOptions(unaddedTags)}>
<Selector>
<SelectorTitle>
<PlusCircledIcon style={{ margin: "auto 0" }} />
<PlusCircledIcon style={{ margin: 'auto 0' }} />
Tag
</SelectorTitle>
</Selector>
</PopoverTrigger>
<PopoverPortal>
<PopoverContent side='top' sideOffset={5} align='start'>
<PopoverContent side="top" sideOffset={5} align="start">
<TagSelectorContent>
<TagOptionsContainer>
{ tagOptions.length === 0 &&
<AllTagsAdded>
{ errMessage }
</AllTagsAdded>
}
{ tagOptions.map((tag) => (
<TagOption
key={tag._id}
onClick={() => onClickTag(tag)}
>
{ tag.name }
{projectTags.length === 0 && <DefaultTagMessage>No tags available</DefaultTagMessage>}
{projectTags.length > 0 && tagOptions.length === 0 && (
<DefaultTagMessage>All tags added</DefaultTagMessage>
)}
{tagOptions.map((tag) => (
<TagOption key={tag._id} onClick={() => onClickTag(tag)}>
{tag.name}
</TagOption>
))}
</TagOptionsContainer>
Expand Down Expand Up @@ -203,4 +201,4 @@ export const TagSelector = ({
</PopoverPortal>
</PopoverRoot>
);
}
};
58 changes: 29 additions & 29 deletions src/features/loupe/ImageTagsToolbar.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useEffect, useState } from 'react';
import { styled } from "../../theme/stitches.config";
import { styled } from '../../theme/stitches.config';
import { mauve } from '@radix-ui/colors';
import { ImageTag } from "./ImageTag.jsx";
import { ImageTag } from './ImageTag.jsx';
import { TagSelector } from '../../components/TagSelector.jsx';
import { editTag } from '../review/reviewSlice.js';
import { useDispatch } from 'react-redux';
Expand All @@ -11,19 +11,19 @@ const Toolbar = styled('div', {
height: 'calc(32px + $2 + $2)',
width: '100%',
borderBottom: '1px solid $border',
position: 'relative'
position: 'relative',
});

const TagsContainer = styled('div', {
position: 'relative',
width: '100%'
width: '100%',
});

const TagSelectorContainer = styled('div', {
margin: '$2',
marginRight: '0',
display: 'grid',
placeItems: 'center'
placeItems: 'center',
});

const ScrollContainer = styled('div', {
Expand All @@ -43,32 +43,31 @@ const ScrollContainer = styled('div', {
const Separator = styled('div', {
width: '1px',
backgroundColor: mauve.mauve6,
margin: '$2 10px'
margin: '$2 10px',
});

const getImageTagInfo = (imageTags, projectTags) => {
return projectTags.filter((t) => {
return imageTags.find((it) => it === t._id) !== undefined
return imageTags.find((it) => it === t._id) !== undefined;
});
}
};

const getUnaddedTags = (imageTags, projectTags) => {
return projectTags.filter((t) => imageTags.findIndex((it) => it === t._id) === -1)
}
return projectTags.filter((t) => imageTags.findIndex((it) => it === t._id) === -1);
};

// Sort alphabetically with JS magic
const orderUnaddedTags = (unaddedTags) => {
return unaddedTags.sort((a, b) => a.name.localeCompare(b.name));
}
};

export const ImageTagsToolbar = ({
image,
projectTags
}) => {
export const ImageTagsToolbar = ({ image, projectTags }) => {
const dispatch = useDispatch();

const [imageTags, setImageTags] = useState(getImageTagInfo(image.tags, projectTags));
const [unaddedTags, setUnaddedTags] = useState(orderUnaddedTags(getUnaddedTags(image.tags, projectTags)));
const [unaddedTags, setUnaddedTags] = useState(
orderUnaddedTags(getUnaddedTags(image.tags, projectTags)),
);

// image._id -> when the enlarged image changes
// projectTags -> so that newly added project tags show up without refreshing
Expand All @@ -80,44 +79,45 @@ export const ImageTagsToolbar = ({
const onDeleteTag = (tagId) => {
const deleteTagDto = {
tagId: tagId,
imageId: image._id
imageId: image._id,
};
const idx = imageTags.findIndex((t) => t._id === tagId)
const idx = imageTags.findIndex((t) => t._id === tagId);
if (idx >= 0) {
const removed = imageTags.splice(idx, 1)
setImageTags([...imageTags])
setUnaddedTags(orderUnaddedTags([...unaddedTags, ...removed]))
const removed = imageTags.splice(idx, 1);
setImageTags([...imageTags]);
setUnaddedTags(orderUnaddedTags([...unaddedTags, ...removed]));
}
dispatch(editTag('delete', deleteTagDto));
}
};

const onAddTag = (tag) => {
const addTagDto = {
tagId: tag._id,
imageId: image._id
imageId: image._id,
};
const idx = unaddedTags.findIndex((t) => t._id === tag._id)
const idx = unaddedTags.findIndex((t) => t._id === tag._id);
if (idx >= 0) {
setImageTags([...imageTags, tag]);
unaddedTags.splice(idx, 1);
setUnaddedTags(orderUnaddedTags([...unaddedTags]));
}
dispatch(editTag('create', addTagDto));
}
};

return (
<Toolbar>
<TagSelectorContainer>
<TagSelector
tagList={unaddedTags}
<TagSelector
projectTags={projectTags}
unaddedTags={unaddedTags}
onAddTag={onAddTag}
imageId={image._id}
/>
</TagSelectorContainer>
<Separator />
<TagsContainer>
<ScrollContainer>
{ imageTags.map(({ _id, name, color }) => (
{imageTags.map(({ _id, name, color }) => (
<ImageTag
key={_id}
id={_id}
Expand All @@ -130,4 +130,4 @@ export const ImageTagsToolbar = ({
</TagsContainer>
</Toolbar>
);
}
};

0 comments on commit 8d5799a

Please sign in to comment.