overhaul tags

This commit is contained in:
jessop 2020-03-06 17:11:40 -05:00
parent f7d31bda33
commit c630482eab
6 changed files with 82 additions and 35 deletions

View file

@ -1010,5 +1010,10 @@
"Only apply a few tags that are relevant to your content, and use the Mature tag as appropriate. Tag abuse will not be tolerated.": "Only apply a few tags that are relevant to your content, and use the Mature tag as appropriate. Tag abuse will not be tolerated.",
"Add relevant tags...": "Add relevant tags...",
"Enter up to five (5) tags that are relevant to your content, and use the Mature tag as appropriate. Tag abuse will not be tolerated.": "Enter up to five (5) tags that are relevant to your content, and use the Mature tag as appropriate. Tag abuse will not be tolerated.",
"Sorry, your request timed out. Modify your options or %again%": "Sorry, your request timed out. Modify your options or %again%"
"Sorry, your request timed out. Modify your options or %again%": "Sorry, your request timed out. Modify your options or %again%",
"gaming, crypto": "gaming, crypto",
"Autocomplete": "Autocomplete",
"Followed Tags": "Followed Tags",
"Add tags that are relevant to your content. If mature content, ensure it is tagged mature. Tag abuse and missing mature tags will not be tolerated.": "Add tags that are relevant to your content. If mature content, ensure it is tagged mature. Tag abuse and missing mature tags will not be tolerated.",
"%selectTagsLabel% (%number% left)": "%selectTagsLabel% (%number% left)"
}

View file

@ -90,7 +90,6 @@ function PublishForm(props: Props) {
const TAGS_LIMIT = 5;
const formDisabled = (!filePath && !editingURI) || publishing;
const isInProgress = filePath || editingURI || name || title;
const tagsCount = tags && tags.length;
// If they are editing, they don't need a new file chosen
const formValidLessFile =
@ -156,14 +155,14 @@ function PublishForm(props: Props) {
empty={__('No tags added')}
limit={TAGS_LIMIT}
help={__(
'Enter up to five (5) tags that are relevant to your content, and use the Mature tag as appropriate. Tag abuse will not be tolerated.'
'Add tags that are relevant to your content. If mature content, ensure it is tagged mature. Tag abuse and missing mature tags will not be tolerated.'
)}
placeholder={__('Add relevant tags...')}
placeholder={__('gaming, crypto')}
onSelect={newTags => {
const validatedTags = [];
newTags.forEach(newTag => {
if (!tags.some(tag => tag.name === newTag.name)) {
if (tagsCount + validatedTags.length < TAGS_LIMIT) validatedTags.push(newTag);
validatedTags.push(newTag);
}
});
updatePublishForm({ tags: [...tags, ...validatedTags] });

View file

@ -31,6 +31,7 @@ export default function Tag(props: Props) {
disabled={disabled}
title={title}
className={classnames('tag', {
'tag--disabled': disabled === true,
'tag--large': type === 'large',
'tag--remove': type === 'remove',
// tag--add only adjusts the color, which causes issues with mature tag color clashing

View file

@ -3,6 +3,7 @@ import React, { useState } from 'react';
import { Form, FormField } from 'component/common/form';
import Tag from 'component/tag';
import { setUnion, setDifference } from 'util/set-operations';
import I18nMessage from '../i18nMessage';
type Props = {
tagsPassedIn: Array<Tag>,
@ -17,6 +18,7 @@ type Props = {
placeholder?: string,
label?: string,
disabled?: boolean,
limit?: number,
};
/*
@ -40,6 +42,7 @@ export default function TagsSearch(props: Props) {
placeholder,
label,
disabled,
limit,
} = props;
const [newTag, setNewTag] = useState('');
const doesTagMatch = name => {
@ -56,6 +59,8 @@ export default function TagsSearch(props: Props) {
const remainingFollowedTagsSet = setDifference(followedTagsSet, selectedTagsSet);
const suggestedTagsSet = setUnion(remainingFollowedTagsSet, unfollowedTagsSet);
const countWithoutMature = selectedTagsSet.has('mature') ? selectedTagsSet.size - 1 : selectedTagsSet.size;
const maxed = Boolean(limit && countWithoutMature >= limit);
const suggestedTags = Array.from(suggestedTagsSet)
.filter(doesTagMatch)
.slice(0, 5);
@ -110,38 +115,70 @@ export default function TagsSearch(props: Props) {
return (
<React.Fragment>
<Form className="tags__input-wrapper" onSubmit={handleSubmit}>
<label>{label || __('Following')}</label>
<ul className="tags--remove">
{tagsPassedIn.map(tag => (
<Tag
key={`passed${tag.name}`}
name={tag.name}
type="remove"
onClick={() => {
onRemove(tag);
<label>
{limit ? (
<I18nMessage
tokens={{
number: 5 - countWithoutMature,
selectTagsLabel: label,
}}
/>
))}
<li>
<FormField
autoFocus={!disableAutoFocus}
className="tag__input"
onChange={onChange}
placeholder={placeholder || __('Follow more tags')}
type="text"
value={newTag}
disabled={disabled}
/>
</li>
>
%selectTagsLabel% (%number% left)
</I18nMessage>
) : (
label || __('Following')
)}
</label>
<ul className="tags--remove">
{!tagsPassedIn.length && <Tag key={`placeholder-tag`} name={'example'} disabled type={'remove'} />}
{Boolean(tagsPassedIn.length) &&
tagsPassedIn.map(tag => (
<Tag
key={`passed${tag.name}`}
name={tag.name}
type="remove"
onClick={() => {
onRemove(tag);
}}
/>
))}
</ul>
<FormField
autoFocus={!disableAutoFocus}
className="tag__input"
onChange={onChange}
placeholder={placeholder || __('gaming, crypto')}
type="text"
value={newTag}
disabled={disabled}
label={'Add Tags'}
/>
<section>
<label>{newTag.length ? __('Autocomplete') : __('Followed Tags')}</label>
<ul className="tags">
{Boolean(newTag.length) && !suggestedTags.includes(newTag) && (
<Tag
disabled={newTag !== 'mature' && maxed}
key={`entered${newTag}`}
name={newTag}
type="add"
onClick={newTag.includes('') ? e => handleSubmit(e) : e => handleTagClick(newTag)}
/>
)}
{suggestedTags.map(tag => (
<Tag
disabled={tag !== 'mature' && maxed}
key={`suggested${tag}`}
name={tag}
type="add"
onClick={() => handleTagClick(tag)}
/>
))}
{!suggestedTags.length && <p className="empty tags__empty-message">No suggested tags</p>}
</ul>
</section>
</Form>
<label>{__('Suggested')}</label>
<ul className="tags">
{suggestedTags.map(tag => (
<Tag disabled={disabled} key={`suggested${tag}`} name={tag} type="add" onClick={() => handleTagClick(tag)} />
))}
{!suggestedTags.length && <p className="empty tags__empty-message">No suggested tags</p>}
</ul>
</React.Fragment>
);
}

View file

@ -107,7 +107,7 @@ export default function TagsSelect(props: Props) {
disableAutoFocus={disableAutoFocus}
tagsPassedIn={tagsToDisplay}
placeholder={placeholder}
disabled={limit && tagCount >= limit}
limit={limit}
/>
</React.Fragment>
}

View file

@ -43,6 +43,7 @@
height: var(--tag-height);
padding: calc(var(--spacing-miniscule) + 1px) var(--spacing-small);
background-color: var(--color-input-bg);
margin-bottom: var(--spacing-medium);
}
}
@ -55,6 +56,10 @@
max-width: 20rem;
}
.tag--disabled {
opacity: 0.3;
}
.tag--large {
height: var(--height-input);
padding: 0 var(--spacing-s);