mirror of
https://github.com/LBRYFoundation/lbry-desktop.git
synced 2025-08-30 17:01:25 +00:00
overhaul tags
This commit is contained in:
parent
f7d31bda33
commit
c630482eab
6 changed files with 82 additions and 35 deletions
|
@ -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.",
|
"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...",
|
"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.",
|
"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)"
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,7 +90,6 @@ function PublishForm(props: Props) {
|
||||||
const TAGS_LIMIT = 5;
|
const TAGS_LIMIT = 5;
|
||||||
const formDisabled = (!filePath && !editingURI) || publishing;
|
const formDisabled = (!filePath && !editingURI) || publishing;
|
||||||
const isInProgress = filePath || editingURI || name || title;
|
const isInProgress = filePath || editingURI || name || title;
|
||||||
const tagsCount = tags && tags.length;
|
|
||||||
|
|
||||||
// If they are editing, they don't need a new file chosen
|
// If they are editing, they don't need a new file chosen
|
||||||
const formValidLessFile =
|
const formValidLessFile =
|
||||||
|
@ -156,14 +155,14 @@ function PublishForm(props: Props) {
|
||||||
empty={__('No tags added')}
|
empty={__('No tags added')}
|
||||||
limit={TAGS_LIMIT}
|
limit={TAGS_LIMIT}
|
||||||
help={__(
|
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 => {
|
onSelect={newTags => {
|
||||||
const validatedTags = [];
|
const validatedTags = [];
|
||||||
newTags.forEach(newTag => {
|
newTags.forEach(newTag => {
|
||||||
if (!tags.some(tag => tag.name === newTag.name)) {
|
if (!tags.some(tag => tag.name === newTag.name)) {
|
||||||
if (tagsCount + validatedTags.length < TAGS_LIMIT) validatedTags.push(newTag);
|
validatedTags.push(newTag);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
updatePublishForm({ tags: [...tags, ...validatedTags] });
|
updatePublishForm({ tags: [...tags, ...validatedTags] });
|
||||||
|
|
|
@ -31,6 +31,7 @@ export default function Tag(props: Props) {
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
title={title}
|
title={title}
|
||||||
className={classnames('tag', {
|
className={classnames('tag', {
|
||||||
|
'tag--disabled': disabled === true,
|
||||||
'tag--large': type === 'large',
|
'tag--large': type === 'large',
|
||||||
'tag--remove': type === 'remove',
|
'tag--remove': type === 'remove',
|
||||||
// tag--add only adjusts the color, which causes issues with mature tag color clashing
|
// tag--add only adjusts the color, which causes issues with mature tag color clashing
|
||||||
|
|
|
@ -3,6 +3,7 @@ import React, { useState } from 'react';
|
||||||
import { Form, FormField } from 'component/common/form';
|
import { Form, FormField } from 'component/common/form';
|
||||||
import Tag from 'component/tag';
|
import Tag from 'component/tag';
|
||||||
import { setUnion, setDifference } from 'util/set-operations';
|
import { setUnion, setDifference } from 'util/set-operations';
|
||||||
|
import I18nMessage from '../i18nMessage';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
tagsPassedIn: Array<Tag>,
|
tagsPassedIn: Array<Tag>,
|
||||||
|
@ -17,6 +18,7 @@ type Props = {
|
||||||
placeholder?: string,
|
placeholder?: string,
|
||||||
label?: string,
|
label?: string,
|
||||||
disabled?: boolean,
|
disabled?: boolean,
|
||||||
|
limit?: number,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -40,6 +42,7 @@ export default function TagsSearch(props: Props) {
|
||||||
placeholder,
|
placeholder,
|
||||||
label,
|
label,
|
||||||
disabled,
|
disabled,
|
||||||
|
limit,
|
||||||
} = props;
|
} = props;
|
||||||
const [newTag, setNewTag] = useState('');
|
const [newTag, setNewTag] = useState('');
|
||||||
const doesTagMatch = name => {
|
const doesTagMatch = name => {
|
||||||
|
@ -56,6 +59,8 @@ export default function TagsSearch(props: Props) {
|
||||||
const remainingFollowedTagsSet = setDifference(followedTagsSet, selectedTagsSet);
|
const remainingFollowedTagsSet = setDifference(followedTagsSet, selectedTagsSet);
|
||||||
const suggestedTagsSet = setUnion(remainingFollowedTagsSet, unfollowedTagsSet);
|
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)
|
const suggestedTags = Array.from(suggestedTagsSet)
|
||||||
.filter(doesTagMatch)
|
.filter(doesTagMatch)
|
||||||
.slice(0, 5);
|
.slice(0, 5);
|
||||||
|
@ -110,38 +115,70 @@ export default function TagsSearch(props: Props) {
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<Form className="tags__input-wrapper" onSubmit={handleSubmit}>
|
<Form className="tags__input-wrapper" onSubmit={handleSubmit}>
|
||||||
<label>{label || __('Following')}</label>
|
<label>
|
||||||
<ul className="tags--remove">
|
{limit ? (
|
||||||
{tagsPassedIn.map(tag => (
|
<I18nMessage
|
||||||
<Tag
|
tokens={{
|
||||||
key={`passed${tag.name}`}
|
number: 5 - countWithoutMature,
|
||||||
name={tag.name}
|
selectTagsLabel: label,
|
||||||
type="remove"
|
|
||||||
onClick={() => {
|
|
||||||
onRemove(tag);
|
|
||||||
}}
|
}}
|
||||||
/>
|
>
|
||||||
))}
|
%selectTagsLabel% (%number% left)
|
||||||
<li>
|
</I18nMessage>
|
||||||
<FormField
|
) : (
|
||||||
autoFocus={!disableAutoFocus}
|
label || __('Following')
|
||||||
className="tag__input"
|
)}
|
||||||
onChange={onChange}
|
</label>
|
||||||
placeholder={placeholder || __('Follow more tags')}
|
<ul className="tags--remove">
|
||||||
type="text"
|
{!tagsPassedIn.length && <Tag key={`placeholder-tag`} name={'example'} disabled type={'remove'} />}
|
||||||
value={newTag}
|
{Boolean(tagsPassedIn.length) &&
|
||||||
disabled={disabled}
|
tagsPassedIn.map(tag => (
|
||||||
/>
|
<Tag
|
||||||
</li>
|
key={`passed${tag.name}`}
|
||||||
|
name={tag.name}
|
||||||
|
type="remove"
|
||||||
|
onClick={() => {
|
||||||
|
onRemove(tag);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
</ul>
|
</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>
|
</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>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,7 +107,7 @@ export default function TagsSelect(props: Props) {
|
||||||
disableAutoFocus={disableAutoFocus}
|
disableAutoFocus={disableAutoFocus}
|
||||||
tagsPassedIn={tagsToDisplay}
|
tagsPassedIn={tagsToDisplay}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
disabled={limit && tagCount >= limit}
|
limit={limit}
|
||||||
/>
|
/>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
height: var(--tag-height);
|
height: var(--tag-height);
|
||||||
padding: calc(var(--spacing-miniscule) + 1px) var(--spacing-small);
|
padding: calc(var(--spacing-miniscule) + 1px) var(--spacing-small);
|
||||||
background-color: var(--color-input-bg);
|
background-color: var(--color-input-bg);
|
||||||
|
margin-bottom: var(--spacing-medium);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,6 +56,10 @@
|
||||||
max-width: 20rem;
|
max-width: 20rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tag--disabled {
|
||||||
|
opacity: 0.3;
|
||||||
|
}
|
||||||
|
|
||||||
.tag--large {
|
.tag--large {
|
||||||
height: var(--height-input);
|
height: var(--height-input);
|
||||||
padding: 0 var(--spacing-s);
|
padding: 0 var(--spacing-s);
|
||||||
|
|
Loading…
Add table
Reference in a new issue