mirror of
https://github.com/LemmyNet/lemmy-ui.git
synced 2024-12-23 03:11:25 +00:00
Merge branch 'main' into more_accessibility
This commit is contained in:
commit
58bbb51f8f
33 changed files with 246 additions and 423 deletions
|
@ -11,6 +11,10 @@
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.pointer-events {
|
||||||
|
pointer-events: auto !important;
|
||||||
|
}
|
||||||
|
|
||||||
.no-click {
|
.no-click {
|
||||||
pointer-events:none;
|
pointer-events:none;
|
||||||
opacity: 0.65;
|
opacity: 0.65;
|
||||||
|
|
|
@ -25,6 +25,7 @@ import autosize from 'autosize';
|
||||||
import { SiteForm } from './site-form';
|
import { SiteForm } from './site-form';
|
||||||
import { UserListing } from './user-listing';
|
import { UserListing } from './user-listing';
|
||||||
import { HtmlTags } from './html-tags';
|
import { HtmlTags } from './html-tags';
|
||||||
|
import { Spinner } from './icon';
|
||||||
import { i18n } from '../i18next';
|
import { i18n } from '../i18next';
|
||||||
import { InitialFetchRequest } from 'shared/interfaces';
|
import { InitialFetchRequest } from 'shared/interfaces';
|
||||||
|
|
||||||
|
@ -109,9 +110,7 @@ export class AdminSettings extends Component<any, AdminSettingsState> {
|
||||||
/>
|
/>
|
||||||
{this.state.loading ? (
|
{this.state.loading ? (
|
||||||
<h5>
|
<h5>
|
||||||
<svg class="icon icon-spinner spin">
|
<Spinner />
|
||||||
<use xlinkHref="#icon-spinner"></use>
|
|
||||||
</svg>
|
|
||||||
</h5>
|
</h5>
|
||||||
) : (
|
) : (
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
@ -185,9 +184,7 @@ export class AdminSettings extends Component<any, AdminSettingsState> {
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<button type="submit" class="btn btn-secondary mr-2">
|
<button type="submit" class="btn btn-secondary mr-2">
|
||||||
{this.state.siteConfigLoading ? (
|
{this.state.siteConfigLoading ? (
|
||||||
<svg class="icon icon-spinner spin">
|
<Spinner />
|
||||||
<use xlinkHref="#icon-spinner"></use>
|
|
||||||
</svg>
|
|
||||||
) : (
|
) : (
|
||||||
capitalizeFirstLetter(i18n.t('save'))
|
capitalizeFirstLetter(i18n.t('save'))
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { Component } from 'inferno';
|
import { Component } from 'inferno';
|
||||||
import { i18n } from '../i18next';
|
import { i18n } from '../i18next';
|
||||||
|
import { Icon } from './icon';
|
||||||
|
|
||||||
interface CakeDayProps {
|
interface CakeDayProps {
|
||||||
creatorName: string;
|
creatorName: string;
|
||||||
|
@ -12,9 +13,7 @@ export class CakeDay extends Component<CakeDayProps, any> {
|
||||||
className={`mx-2 d-inline-block unselectable pointer`}
|
className={`mx-2 d-inline-block unselectable pointer`}
|
||||||
data-tippy-content={this.cakeDayTippy()}
|
data-tippy-content={this.cakeDayTippy()}
|
||||||
>
|
>
|
||||||
<svg class="icon icon-inline">
|
<Icon icon="cake" classes="icon-inline" />
|
||||||
<use xlinkHref="#icon-cake"></use>
|
|
||||||
</svg>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ import { WebSocketService, UserService } from '../services';
|
||||||
import { i18n } from '../i18next';
|
import { i18n } from '../i18next';
|
||||||
import { T } from 'inferno-i18next';
|
import { T } from 'inferno-i18next';
|
||||||
import { MarkdownTextArea } from './markdown-textarea';
|
import { MarkdownTextArea } from './markdown-textarea';
|
||||||
|
import { Icon } from './icon';
|
||||||
|
|
||||||
interface CommentFormProps {
|
interface CommentFormProps {
|
||||||
postId?: number;
|
postId?: number;
|
||||||
|
@ -84,9 +85,7 @@ export class CommentForm extends Component<CommentFormProps, CommentFormState> {
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div class="alert alert-light" role="alert">
|
<div class="alert alert-light" role="alert">
|
||||||
<svg class="icon icon-inline mr-2">
|
<Icon icon="alert-triangle" classes="icon-inline mr-2" />
|
||||||
<use xlinkHref="#icon-alert-triangle"></use>
|
|
||||||
</svg>
|
|
||||||
<T i18nKey="must_login" class="d-inline">
|
<T i18nKey="must_login" class="d-inline">
|
||||||
#
|
#
|
||||||
<Link className="alert-link" to="/login">
|
<Link className="alert-link" to="/login">
|
||||||
|
|
|
@ -36,6 +36,7 @@ import { CommentForm } from './comment-form';
|
||||||
import { CommentNodes } from './comment-nodes';
|
import { CommentNodes } from './comment-nodes';
|
||||||
import { UserListing } from './user-listing';
|
import { UserListing } from './user-listing';
|
||||||
import { CommunityLink } from './community-link';
|
import { CommunityLink } from './community-link';
|
||||||
|
import { Icon, Spinner } from './icon';
|
||||||
import { i18n } from '../i18next';
|
import { i18n } from '../i18next';
|
||||||
|
|
||||||
interface CommentNodeState {
|
interface CommentNodeState {
|
||||||
|
@ -260,13 +261,12 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
{this.state.readLoading ? (
|
{this.state.readLoading ? (
|
||||||
this.loadingIcon
|
this.loadingIcon
|
||||||
) : (
|
) : (
|
||||||
<svg
|
<Icon
|
||||||
class={`icon icon-inline ${
|
icon="check"
|
||||||
|
classes={`icon-inline ${
|
||||||
this.commentOrMentionRead && 'text-success'
|
this.commentOrMentionRead && 'text-success'
|
||||||
}`}
|
}`}
|
||||||
>
|
/>
|
||||||
<use xlinkHref="#icon-check"></use>
|
|
||||||
</svg>
|
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
|
@ -280,9 +280,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
data-tippy-content={i18n.t('upvote')}
|
data-tippy-content={i18n.t('upvote')}
|
||||||
aria-label={i18n.t('upvote')}
|
aria-label={i18n.t('upvote')}
|
||||||
>
|
>
|
||||||
<svg class="icon icon-inline">
|
<Icon icon="arrow-up1" classes="icon-inline" />
|
||||||
<use xlinkHref="#icon-arrow-up1"></use>
|
|
||||||
</svg>
|
|
||||||
{this.state.upvotes !== this.state.score && (
|
{this.state.upvotes !== this.state.score && (
|
||||||
<span class="ml-1">{this.state.upvotes}</span>
|
<span class="ml-1">{this.state.upvotes}</span>
|
||||||
)}
|
)}
|
||||||
|
@ -298,9 +296,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
data-tippy-content={i18n.t('downvote')}
|
data-tippy-content={i18n.t('downvote')}
|
||||||
aria-label={i18n.t('downvote')}
|
aria-label={i18n.t('downvote')}
|
||||||
>
|
>
|
||||||
<svg class="icon icon-inline">
|
<Icon icon="arrow-down1" classes="icon-inline" />
|
||||||
<use xlinkHref="#icon-arrow-down1"></use>
|
|
||||||
</svg>
|
|
||||||
{this.state.upvotes !== this.state.score && (
|
{this.state.upvotes !== this.state.score && (
|
||||||
<span class="ml-1">{this.state.downvotes}</span>
|
<span class="ml-1">{this.state.downvotes}</span>
|
||||||
)}
|
)}
|
||||||
|
@ -312,9 +308,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
data-tippy-content={i18n.t('reply')}
|
data-tippy-content={i18n.t('reply')}
|
||||||
aria-label={i18n.t('reply')}
|
aria-label={i18n.t('reply')}
|
||||||
>
|
>
|
||||||
<svg class="icon icon-inline">
|
<Icon icon="reply1" classes="icon-inline" />
|
||||||
<use xlinkHref="#icon-reply1"></use>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
{!this.state.showAdvanced ? (
|
{!this.state.showAdvanced ? (
|
||||||
<button
|
<button
|
||||||
|
@ -323,9 +317,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
data-tippy-content={i18n.t('more')}
|
data-tippy-content={i18n.t('more')}
|
||||||
aria-label={i18n.t('more')}
|
aria-label={i18n.t('more')}
|
||||||
>
|
>
|
||||||
<svg class="icon icon-inline">
|
<Icon icon="more-vertical" classes="icon-inline" />
|
||||||
<use xlinkHref="#icon-more-vertical"></use>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
|
@ -336,9 +328,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
to={`/create_private_message/recipient/${cv.creator.id}`}
|
to={`/create_private_message/recipient/${cv.creator.id}`}
|
||||||
title={i18n.t('message').toLowerCase()}
|
title={i18n.t('message').toLowerCase()}
|
||||||
>
|
>
|
||||||
<svg class="icon">
|
<Icon icon="mail" />
|
||||||
<use xlinkHref="#icon-mail"></use>
|
|
||||||
</svg>
|
|
||||||
</Link>
|
</Link>
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
|
@ -359,13 +349,12 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
{this.state.saveLoading ? (
|
{this.state.saveLoading ? (
|
||||||
this.loadingIcon
|
this.loadingIcon
|
||||||
) : (
|
) : (
|
||||||
<svg
|
<Icon
|
||||||
class={`icon icon-inline ${
|
icon="star"
|
||||||
|
classes={`icon-inline ${
|
||||||
cv.saved && 'text-warning'
|
cv.saved && 'text-warning'
|
||||||
}`}
|
}`}
|
||||||
>
|
/>
|
||||||
<use xlinkHref="#icon-star"></use>
|
|
||||||
</svg>
|
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
|
@ -374,13 +363,12 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
data-tippy-content={i18n.t('view_source')}
|
data-tippy-content={i18n.t('view_source')}
|
||||||
aria-label={i18n.t('view_source')}
|
aria-label={i18n.t('view_source')}
|
||||||
>
|
>
|
||||||
<svg
|
<Icon
|
||||||
class={`icon icon-inline ${
|
icon="file-text"
|
||||||
|
classes={`icon-inline ${
|
||||||
this.state.viewSource && 'text-success'
|
this.state.viewSource && 'text-success'
|
||||||
}`}
|
}`}
|
||||||
>
|
/>
|
||||||
<use xlinkHref="#icon-file-text"></use>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
{this.myComment && (
|
{this.myComment && (
|
||||||
<>
|
<>
|
||||||
|
@ -390,9 +378,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
data-tippy-content={i18n.t('edit')}
|
data-tippy-content={i18n.t('edit')}
|
||||||
aria-label={i18n.t('edit')}
|
aria-label={i18n.t('edit')}
|
||||||
>
|
>
|
||||||
<svg class="icon icon-inline">
|
<Icon icon="edit" classes="icon-inline" />
|
||||||
<use xlinkHref="#icon-edit"></use>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
class="btn btn-link btn-animate text-muted"
|
class="btn btn-link btn-animate text-muted"
|
||||||
|
@ -411,13 +397,12 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
: i18n.t('restore')
|
: i18n.t('restore')
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<svg
|
<Icon
|
||||||
class={`icon icon-inline ${
|
icon="trash"
|
||||||
|
classes={`icon-inline ${
|
||||||
cv.comment.deleted && 'text-danger'
|
cv.comment.deleted && 'text-danger'
|
||||||
}`}
|
}`}
|
||||||
>
|
/>
|
||||||
<use xlinkHref="#icon-trash"></use>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
@ -817,19 +802,13 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
|
||||||
to={`/post/${cv.post.id}/comment/${cv.comment.id}`}
|
to={`/post/${cv.post.id}/comment/${cv.comment.id}`}
|
||||||
title={this.props.showContext ? i18n.t('show_context') : i18n.t('link')}
|
title={this.props.showContext ? i18n.t('show_context') : i18n.t('link')}
|
||||||
>
|
>
|
||||||
<svg class="icon icon-inline">
|
<Icon icon="link" classes="icon-inline" />
|
||||||
<use xlinkHref="#icon-link"></use>
|
|
||||||
</svg>
|
|
||||||
</Link>
|
</Link>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
get loadingIcon() {
|
get loadingIcon() {
|
||||||
return (
|
return <Spinner />;
|
||||||
<svg class="icon icon-spinner spin">
|
|
||||||
<use xlinkHref="#icon-spinner"></use>
|
|
||||||
</svg>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get myComment(): boolean {
|
get myComment(): boolean {
|
||||||
|
|
|
@ -26,6 +26,7 @@ import {
|
||||||
setOptionalAuth,
|
setOptionalAuth,
|
||||||
} from '../utils';
|
} from '../utils';
|
||||||
import { CommunityLink } from './community-link';
|
import { CommunityLink } from './community-link';
|
||||||
|
import { Spinner } from './icon';
|
||||||
import { i18n } from '../i18next';
|
import { i18n } from '../i18next';
|
||||||
import { InitialFetchRequest } from 'shared/interfaces';
|
import { InitialFetchRequest } from 'shared/interfaces';
|
||||||
|
|
||||||
|
@ -104,10 +105,8 @@ export class Communities extends Component<any, CommunitiesState> {
|
||||||
path={this.context.router.route.match.url}
|
path={this.context.router.route.match.url}
|
||||||
/>
|
/>
|
||||||
{this.state.loading ? (
|
{this.state.loading ? (
|
||||||
<h5 class="">
|
<h5>
|
||||||
<svg class="icon icon-spinner spin">
|
<Spinner />
|
||||||
<use xlinkHref="#icon-spinner"></use>
|
|
||||||
</svg>
|
|
||||||
</h5>
|
</h5>
|
||||||
) : (
|
) : (
|
||||||
<div>
|
<div>
|
||||||
|
|
|
@ -24,6 +24,7 @@ import { i18n } from '../i18next';
|
||||||
|
|
||||||
import { MarkdownTextArea } from './markdown-textarea';
|
import { MarkdownTextArea } from './markdown-textarea';
|
||||||
import { ImageUploadForm } from './image-upload-form';
|
import { ImageUploadForm } from './image-upload-form';
|
||||||
|
import { Icon, Spinner } from './icon';
|
||||||
|
|
||||||
interface CommunityFormProps {
|
interface CommunityFormProps {
|
||||||
community_view?: CommunityView; // If a community is given, that means this is an edit
|
community_view?: CommunityView; // If a community is given, that means this is an edit
|
||||||
|
@ -132,9 +133,7 @@ export class CommunityForm extends Component<
|
||||||
class="pointer unselectable ml-2 text-muted"
|
class="pointer unselectable ml-2 text-muted"
|
||||||
data-tippy-content={i18n.t('name_explain')}
|
data-tippy-content={i18n.t('name_explain')}
|
||||||
>
|
>
|
||||||
<svg class="icon icon-inline">
|
<Icon icon="help-circle" classes="icon-inline" />
|
||||||
<use xlinkHref="#icon-help-circle"></use>
|
|
||||||
</svg>
|
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
|
@ -160,9 +159,7 @@ export class CommunityForm extends Component<
|
||||||
class="pointer unselectable ml-2 text-muted"
|
class="pointer unselectable ml-2 text-muted"
|
||||||
data-tippy-content={i18n.t('display_name_explain')}
|
data-tippy-content={i18n.t('display_name_explain')}
|
||||||
>
|
>
|
||||||
<svg class="icon icon-inline">
|
<Icon icon="help-circle" classes="icon-inline" />
|
||||||
<use xlinkHref="#icon-help-circle"></use>
|
|
||||||
</svg>
|
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
|
@ -252,9 +249,7 @@ export class CommunityForm extends Component<
|
||||||
disabled={this.state.loading}
|
disabled={this.state.loading}
|
||||||
>
|
>
|
||||||
{this.state.loading ? (
|
{this.state.loading ? (
|
||||||
<svg class="icon icon-spinner spin">
|
<Spinner />
|
||||||
<use xlinkHref="#icon-spinner"></use>
|
|
||||||
</svg>
|
|
||||||
) : this.props.community_view ? (
|
) : this.props.community_view ? (
|
||||||
capitalizeFirstLetter(i18n.t('save'))
|
capitalizeFirstLetter(i18n.t('save'))
|
||||||
) : (
|
) : (
|
||||||
|
|
|
@ -31,6 +31,7 @@ import { DataTypeSelect } from './data-type-select';
|
||||||
import { Sidebar } from './sidebar';
|
import { Sidebar } from './sidebar';
|
||||||
import { CommunityLink } from './community-link';
|
import { CommunityLink } from './community-link';
|
||||||
import { BannerIconHeader } from './banner-icon-header';
|
import { BannerIconHeader } from './banner-icon-header';
|
||||||
|
import { Icon, Spinner } from './icon';
|
||||||
import {
|
import {
|
||||||
wsJsonToRes,
|
wsJsonToRes,
|
||||||
fetchLimit,
|
fetchLimit,
|
||||||
|
@ -244,9 +245,7 @@ export class Community extends Component<any, State> {
|
||||||
<div class="container">
|
<div class="container">
|
||||||
{this.state.communityLoading ? (
|
{this.state.communityLoading ? (
|
||||||
<h5>
|
<h5>
|
||||||
<svg class="icon icon-spinner spin">
|
<Spinner />
|
||||||
<use xlinkHref="#icon-spinner"></use>
|
|
||||||
</svg>
|
|
||||||
</h5>
|
</h5>
|
||||||
) : (
|
) : (
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
@ -283,9 +282,7 @@ export class Community extends Component<any, State> {
|
||||||
return this.state.dataType == DataType.Post ? (
|
return this.state.dataType == DataType.Post ? (
|
||||||
this.state.postsLoading ? (
|
this.state.postsLoading ? (
|
||||||
<h5>
|
<h5>
|
||||||
<svg class="icon icon-spinner spin">
|
<Spinner />
|
||||||
<use xlinkHref="#icon-spinner"></use>
|
|
||||||
</svg>
|
|
||||||
</h5>
|
</h5>
|
||||||
) : (
|
) : (
|
||||||
<PostListings
|
<PostListings
|
||||||
|
@ -297,9 +294,7 @@ export class Community extends Component<any, State> {
|
||||||
)
|
)
|
||||||
) : this.state.commentsLoading ? (
|
) : this.state.commentsLoading ? (
|
||||||
<h5>
|
<h5>
|
||||||
<svg class="icon icon-spinner spin">
|
<Spinner />
|
||||||
<use xlinkHref="#icon-spinner"></use>
|
|
||||||
</svg>
|
|
||||||
</h5>
|
</h5>
|
||||||
) : (
|
) : (
|
||||||
<CommentNodes
|
<CommentNodes
|
||||||
|
@ -350,9 +345,7 @@ export class Community extends Component<any, State> {
|
||||||
title="RSS"
|
title="RSS"
|
||||||
rel="noopener"
|
rel="noopener"
|
||||||
>
|
>
|
||||||
<svg class="icon text-muted small">
|
<Icon icon="rss" classes="text-muted small" />
|
||||||
<use xlinkHref="#icon-rss"></use>
|
|
||||||
</svg>
|
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -2,6 +2,7 @@ import { Component } from 'inferno';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
import { CommunityForm } from './community-form';
|
import { CommunityForm } from './community-form';
|
||||||
import { HtmlTags } from './html-tags';
|
import { HtmlTags } from './html-tags';
|
||||||
|
import { Spinner } from './icon';
|
||||||
import {
|
import {
|
||||||
CommunityView,
|
CommunityView,
|
||||||
UserOperation,
|
UserOperation,
|
||||||
|
@ -77,9 +78,7 @@ export class CreateCommunity extends Component<any, CreateCommunityState> {
|
||||||
/>
|
/>
|
||||||
{this.state.loading ? (
|
{this.state.loading ? (
|
||||||
<h5>
|
<h5>
|
||||||
<svg class="icon icon-spinner spin">
|
<Spinner />
|
||||||
<use xlinkHref="#icon-spinner"></use>
|
|
||||||
</svg>
|
|
||||||
</h5>
|
</h5>
|
||||||
) : (
|
) : (
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
|
|
@ -2,6 +2,7 @@ import { Component } from 'inferno';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
import { PostForm } from './post-form';
|
import { PostForm } from './post-form';
|
||||||
import { HtmlTags } from './html-tags';
|
import { HtmlTags } from './html-tags';
|
||||||
|
import { Spinner } from './icon';
|
||||||
import {
|
import {
|
||||||
authField,
|
authField,
|
||||||
isBrowser,
|
isBrowser,
|
||||||
|
@ -95,9 +96,7 @@ export class CreatePost extends Component<any, CreatePostState> {
|
||||||
/>
|
/>
|
||||||
{this.state.loading ? (
|
{this.state.loading ? (
|
||||||
<h5>
|
<h5>
|
||||||
<svg class="icon icon-spinner spin">
|
<Spinner />
|
||||||
<use xlinkHref="#icon-spinner"></use>
|
|
||||||
</svg>
|
|
||||||
</h5>
|
</h5>
|
||||||
) : (
|
) : (
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
|
|
@ -2,6 +2,7 @@ import { Component } from 'inferno';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
import { PrivateMessageForm } from './private-message-form';
|
import { PrivateMessageForm } from './private-message-form';
|
||||||
import { HtmlTags } from './html-tags';
|
import { HtmlTags } from './html-tags';
|
||||||
|
import { Spinner } from './icon';
|
||||||
import { UserService, WebSocketService } from '../services';
|
import { UserService, WebSocketService } from '../services';
|
||||||
import {
|
import {
|
||||||
SiteView,
|
SiteView,
|
||||||
|
@ -112,9 +113,7 @@ export class CreatePrivateMessage extends Component<
|
||||||
/>
|
/>
|
||||||
{this.state.loading ? (
|
{this.state.loading ? (
|
||||||
<h5>
|
<h5>
|
||||||
<svg class="icon icon-spinner spin">
|
<Spinner />
|
||||||
<use xlinkHref="#icon-spinner"></use>
|
|
||||||
</svg>
|
|
||||||
</h5>
|
</h5>
|
||||||
) : (
|
) : (
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
|
31
src/shared/components/icon.tsx
Normal file
31
src/shared/components/icon.tsx
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
import { Component } from 'inferno';
|
||||||
|
|
||||||
|
interface IconProps {
|
||||||
|
icon: string;
|
||||||
|
classes?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Icon extends Component<IconProps, any> {
|
||||||
|
constructor(props: any, context: any) {
|
||||||
|
super(props, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<svg class={`icon ${this.props.classes}`}>
|
||||||
|
<title>{this.props.icon}</title>
|
||||||
|
<use xlinkHref={`#icon-${this.props.icon}`}></use>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Spinner extends Component<any, any> {
|
||||||
|
constructor(props: any, context: any) {
|
||||||
|
super(props, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return <Icon icon="spinner" classes="icon-spinner spin" />;
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,7 @@ import { Component, linkEvent } from 'inferno';
|
||||||
import { Post } from 'lemmy-js-client';
|
import { Post } from 'lemmy-js-client';
|
||||||
import { mdToHtml } from '../utils';
|
import { mdToHtml } from '../utils';
|
||||||
import { i18n } from '../i18next';
|
import { i18n } from '../i18next';
|
||||||
|
import { Icon } from './icon';
|
||||||
|
|
||||||
interface FramelyCardProps {
|
interface FramelyCardProps {
|
||||||
post: Post;
|
post: Post;
|
||||||
|
@ -52,9 +53,7 @@ export class IFramelyCard extends Component<
|
||||||
rel="noopener"
|
rel="noopener"
|
||||||
>
|
>
|
||||||
{new URL(post.url).hostname}
|
{new URL(post.url).hostname}
|
||||||
<svg class="ml-1 icon">
|
<Icon icon="external-link" classes="ml-1" />
|
||||||
<use xlinkHref="#icon-external-link"></use>
|
|
||||||
</svg>
|
|
||||||
</a>
|
</a>
|
||||||
</span>,
|
</span>,
|
||||||
]}
|
]}
|
||||||
|
|
|
@ -3,6 +3,7 @@ import { pictrsUri } from '../env';
|
||||||
import { UserService } from '../services';
|
import { UserService } from '../services';
|
||||||
import { toast, randomStr } from '../utils';
|
import { toast, randomStr } from '../utils';
|
||||||
import { i18n } from '../i18next';
|
import { i18n } from '../i18next';
|
||||||
|
import { Icon } from './icon';
|
||||||
|
|
||||||
interface ImageUploadFormProps {
|
interface ImageUploadFormProps {
|
||||||
uploadTitle: string;
|
uploadTitle: string;
|
||||||
|
@ -53,9 +54,7 @@ export class ImageUploadForm extends Component<
|
||||||
onClick={linkEvent(this, this.handleRemoveImage)}
|
onClick={linkEvent(this, this.handleRemoveImage)}
|
||||||
aria-label={i18n.t('remove')}
|
aria-label={i18n.t('remove')}
|
||||||
>
|
>
|
||||||
<svg class="icon mini-overlay">
|
<Icon icon="x" classes="mini-overlay" />
|
||||||
<use xlinkHref="#icon-x"></use>
|
|
||||||
</svg>
|
|
||||||
</a>
|
</a>
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -38,6 +38,7 @@ import { CommentNodes } from './comment-nodes';
|
||||||
import { PrivateMessage } from './private-message';
|
import { PrivateMessage } from './private-message';
|
||||||
import { HtmlTags } from './html-tags';
|
import { HtmlTags } from './html-tags';
|
||||||
import { SortSelect } from './sort-select';
|
import { SortSelect } from './sort-select';
|
||||||
|
import { Icon, Spinner } from './icon';
|
||||||
import { i18n } from '../i18next';
|
import { i18n } from '../i18next';
|
||||||
import { InitialFetchRequest } from 'shared/interfaces';
|
import { InitialFetchRequest } from 'shared/interfaces';
|
||||||
|
|
||||||
|
@ -137,9 +138,7 @@ export class Inbox extends Component<any, InboxState> {
|
||||||
<div class="container">
|
<div class="container">
|
||||||
{this.state.loading ? (
|
{this.state.loading ? (
|
||||||
<h5>
|
<h5>
|
||||||
<svg class="icon icon-spinner spin">
|
<Spinner />
|
||||||
<use xlinkHref="#icon-spinner"></use>
|
|
||||||
</svg>
|
|
||||||
</h5>
|
</h5>
|
||||||
) : (
|
) : (
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
@ -157,9 +156,7 @@ export class Inbox extends Component<any, InboxState> {
|
||||||
title="RSS"
|
title="RSS"
|
||||||
rel="noopener"
|
rel="noopener"
|
||||||
>
|
>
|
||||||
<svg class="icon ml-2 text-muted small">
|
<Icon icon="rss" classes="ml-2 text-muted small" />
|
||||||
<use xlinkHref="#icon-rss"></use>
|
|
||||||
</svg>
|
|
||||||
</a>
|
</a>
|
||||||
</small>
|
</small>
|
||||||
</h5>
|
</h5>
|
||||||
|
|
|
@ -24,6 +24,7 @@ import {
|
||||||
} from '../utils';
|
} from '../utils';
|
||||||
import { i18n } from '../i18next';
|
import { i18n } from '../i18next';
|
||||||
import { HtmlTags } from './html-tags';
|
import { HtmlTags } from './html-tags';
|
||||||
|
import { Icon, Spinner } from './icon';
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
loginForm: LoginForm;
|
loginForm: LoginForm;
|
||||||
|
@ -134,27 +135,21 @@ export class Login extends Component<any, State> {
|
||||||
class="form-control"
|
class="form-control"
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
{validEmail(this.state.loginForm.username_or_email) && (
|
<button
|
||||||
<button
|
type="button"
|
||||||
type="button"
|
onClick={linkEvent(this, this.handlePasswordReset)}
|
||||||
onClick={linkEvent(this, this.handlePasswordReset)}
|
className="btn p-0 btn-link d-inline-block float-right text-muted small font-weight-bold pointer-events"
|
||||||
className="btn p-0 btn-link d-inline-block float-right text-muted small font-weight-bold"
|
disabled={!validEmail(this.state.loginForm.username_or_email)}
|
||||||
>
|
title={i18n.t('no_password_reset')}
|
||||||
{i18n.t('forgot_password')}
|
>
|
||||||
</button>
|
{i18n.t('forgot_password')}
|
||||||
)}
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group row">
|
<div class="form-group row">
|
||||||
<div class="col-sm-10">
|
<div class="col-sm-10">
|
||||||
<button type="submit" class="btn btn-secondary">
|
<button type="submit" class="btn btn-secondary">
|
||||||
{this.state.loginLoading ? (
|
{this.state.loginLoading ? <Spinner /> : i18n.t('login')}
|
||||||
<svg class="icon icon-spinner spin">
|
|
||||||
<use xlinkHref="#icon-spinner"></use>
|
|
||||||
</svg>
|
|
||||||
) : (
|
|
||||||
i18n.t('login')
|
|
||||||
)}
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -204,9 +199,7 @@ export class Login extends Component<any, State> {
|
||||||
/>
|
/>
|
||||||
{!validEmail(this.state.registerForm.email) && (
|
{!validEmail(this.state.registerForm.email) && (
|
||||||
<div class="mt-2 mb-0 alert alert-light" role="alert">
|
<div class="mt-2 mb-0 alert alert-light" role="alert">
|
||||||
<svg class="icon icon-inline mr-2">
|
<Icon icon="alert-triangle" classes="icon-inline mr-2" />
|
||||||
<use xlinkHref="#icon-alert-triangle"></use>
|
|
||||||
</svg>
|
|
||||||
{i18n.t('no_password_reset')}
|
{i18n.t('no_password_reset')}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
@ -262,9 +255,7 @@ export class Login extends Component<any, State> {
|
||||||
onClick={linkEvent(this, this.handleRegenCaptcha)}
|
onClick={linkEvent(this, this.handleRegenCaptcha)}
|
||||||
aria-label={i18n.t('captcha')}
|
aria-label={i18n.t('captcha')}
|
||||||
>
|
>
|
||||||
<svg class="icon icon-refresh-cw">
|
<Icon icon="refresh-cw" classes="icon-refresh-cw" />
|
||||||
<use xlinkHref="#icon-refresh-cw"></use>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
</label>
|
</label>
|
||||||
{this.showCaptcha()}
|
{this.showCaptcha()}
|
||||||
|
@ -304,13 +295,7 @@ export class Login extends Component<any, State> {
|
||||||
<div class="form-group row">
|
<div class="form-group row">
|
||||||
<div class="col-sm-10">
|
<div class="col-sm-10">
|
||||||
<button type="submit" class="btn btn-secondary">
|
<button type="submit" class="btn btn-secondary">
|
||||||
{this.state.registerLoading ? (
|
{this.state.registerLoading ? <Spinner /> : i18n.t('sign_up')}
|
||||||
<svg class="icon icon-spinner spin">
|
|
||||||
<use xlinkHref="#icon-spinner"></use>
|
|
||||||
</svg>
|
|
||||||
) : (
|
|
||||||
i18n.t('sign_up')
|
|
||||||
)}
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -338,9 +323,7 @@ export class Login extends Component<any, State> {
|
||||||
type="button"
|
type="button"
|
||||||
disabled={this.state.captchaPlaying}
|
disabled={this.state.captchaPlaying}
|
||||||
>
|
>
|
||||||
<svg class="icon icon-play">
|
<Icon icon="play" classes="icon-play" />
|
||||||
<use xlinkHref="#icon-play"></use>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -34,6 +34,7 @@ import { SiteForm } from './site-form';
|
||||||
import { UserListing } from './user-listing';
|
import { UserListing } from './user-listing';
|
||||||
import { CommunityLink } from './community-link';
|
import { CommunityLink } from './community-link';
|
||||||
import { BannerIconHeader } from './banner-icon-header';
|
import { BannerIconHeader } from './banner-icon-header';
|
||||||
|
import { Icon, Spinner } from './icon';
|
||||||
import {
|
import {
|
||||||
wsJsonToRes,
|
wsJsonToRes,
|
||||||
mdToHtml,
|
mdToHtml,
|
||||||
|
@ -513,9 +514,7 @@ export class Main extends Component<any, MainState> {
|
||||||
aria-label={i18n.t('edit')}
|
aria-label={i18n.t('edit')}
|
||||||
data-tippy-content={i18n.t('edit')}
|
data-tippy-content={i18n.t('edit')}
|
||||||
>
|
>
|
||||||
<svg class="icon icon-inline">
|
<Icon icon="edit" classes="icon-inline" />
|
||||||
<use xlinkHref="#icon-edit"></use>
|
|
||||||
</svg>
|
|
||||||
</span>
|
</span>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -539,9 +538,7 @@ export class Main extends Component<any, MainState> {
|
||||||
<div class="main-content-wrapper">
|
<div class="main-content-wrapper">
|
||||||
{this.state.loading ? (
|
{this.state.loading ? (
|
||||||
<h5>
|
<h5>
|
||||||
<svg class="icon icon-spinner spin">
|
<Spinner />
|
||||||
<use xlinkHref="#icon-spinner"></use>
|
|
||||||
</svg>
|
|
||||||
</h5>
|
</h5>
|
||||||
) : (
|
) : (
|
||||||
<div>
|
<div>
|
||||||
|
@ -601,9 +598,7 @@ export class Main extends Component<any, MainState> {
|
||||||
rel="noopener"
|
rel="noopener"
|
||||||
title="RSS"
|
title="RSS"
|
||||||
>
|
>
|
||||||
<svg class="icon text-muted small">
|
<Icon icon="rss" classes="text-muted small" />
|
||||||
<use xlinkHref="#icon-rss"></use>
|
|
||||||
</svg>
|
|
||||||
</a>
|
</a>
|
||||||
)}
|
)}
|
||||||
{this.state.listingType == ListingType.Local && (
|
{this.state.listingType == ListingType.Local && (
|
||||||
|
@ -613,9 +608,7 @@ export class Main extends Component<any, MainState> {
|
||||||
rel="noopener"
|
rel="noopener"
|
||||||
title="RSS"
|
title="RSS"
|
||||||
>
|
>
|
||||||
<svg class="icon text-muted small">
|
<Icon icon="rss" classes="text-muted small" />
|
||||||
<use xlinkHref="#icon-rss">#</use>
|
|
||||||
</svg>
|
|
||||||
</a>
|
</a>
|
||||||
)}
|
)}
|
||||||
{UserService.Instance.user &&
|
{UserService.Instance.user &&
|
||||||
|
@ -626,9 +619,7 @@ export class Main extends Component<any, MainState> {
|
||||||
title="RSS"
|
title="RSS"
|
||||||
rel="noopener"
|
rel="noopener"
|
||||||
>
|
>
|
||||||
<svg class="icon text-muted small">
|
<Icon icon="rss" classes="text-muted small" />
|
||||||
<use xlinkHref="#icon-rss">#</use>
|
|
||||||
</svg>
|
|
||||||
</a>
|
</a>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -14,6 +14,7 @@ import { UserService } from '../services';
|
||||||
import autosize from 'autosize';
|
import autosize from 'autosize';
|
||||||
import { i18n } from '../i18next';
|
import { i18n } from '../i18next';
|
||||||
import { pictrsUri } from '../env';
|
import { pictrsUri } from '../env';
|
||||||
|
import { Icon, Spinner } from './icon';
|
||||||
|
|
||||||
interface MarkdownTextAreaProps {
|
interface MarkdownTextAreaProps {
|
||||||
initialContent: string;
|
initialContent: string;
|
||||||
|
@ -151,9 +152,7 @@ export class MarkdownTextArea extends Component<
|
||||||
disabled={this.props.disabled || this.state.loading}
|
disabled={this.props.disabled || this.state.loading}
|
||||||
>
|
>
|
||||||
{this.state.loading ? (
|
{this.state.loading ? (
|
||||||
<svg class="icon icon-spinner spin">
|
<Spinner />
|
||||||
<use xlinkHref="#icon-spinner"></use>
|
|
||||||
</svg>
|
|
||||||
) : (
|
) : (
|
||||||
<span>{this.props.buttonTitle}</span>
|
<span>{this.props.buttonTitle}</span>
|
||||||
)}
|
)}
|
||||||
|
@ -186,9 +185,7 @@ export class MarkdownTextArea extends Component<
|
||||||
aria-label={i18n.t('bold')}
|
aria-label={i18n.t('bold')}
|
||||||
onClick={linkEvent(this, this.handleInsertBold)}
|
onClick={linkEvent(this, this.handleInsertBold)}
|
||||||
>
|
>
|
||||||
<svg class="icon icon-inline">
|
<Icon icon="bold" classes="icon-inline" />
|
||||||
<use xlinkHref="#icon-bold"></use>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
class="btn btn-sm text-muted"
|
class="btn btn-sm text-muted"
|
||||||
|
@ -196,9 +193,7 @@ export class MarkdownTextArea extends Component<
|
||||||
aria-label={i18n.t('italic')}
|
aria-label={i18n.t('italic')}
|
||||||
onClick={linkEvent(this, this.handleInsertItalic)}
|
onClick={linkEvent(this, this.handleInsertItalic)}
|
||||||
>
|
>
|
||||||
<svg class="icon icon-inline">
|
<Icon icon="italic" classes="icon-inline" />
|
||||||
<use xlinkHref="#icon-italic"></use>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
class="btn btn-sm text-muted"
|
class="btn btn-sm text-muted"
|
||||||
|
@ -206,9 +201,7 @@ export class MarkdownTextArea extends Component<
|
||||||
aria-label={i18n.t('link')}
|
aria-label={i18n.t('link')}
|
||||||
onClick={linkEvent(this, this.handleInsertLink)}
|
onClick={linkEvent(this, this.handleInsertLink)}
|
||||||
>
|
>
|
||||||
<svg class="icon icon-inline">
|
<Icon icon="link" classes="icon-inline" />
|
||||||
<use xlinkHref="#icon-link"></use>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
<form class="btn btn-sm text-muted font-weight-bold">
|
<form class="btn btn-sm text-muted font-weight-bold">
|
||||||
<label
|
<label
|
||||||
|
@ -217,13 +210,9 @@ export class MarkdownTextArea extends Component<
|
||||||
data-tippy-content={i18n.t('upload_image')}
|
data-tippy-content={i18n.t('upload_image')}
|
||||||
>
|
>
|
||||||
{this.state.imageLoading ? (
|
{this.state.imageLoading ? (
|
||||||
<svg class="icon icon-spinner spin">
|
<Spinner />
|
||||||
<use xlinkHref="#icon-spinner"></use>
|
|
||||||
</svg>
|
|
||||||
) : (
|
) : (
|
||||||
<svg class="icon icon-inline">
|
<Icon icon="image" classes="icon-inline" />
|
||||||
<use xlinkHref="#icon-image"></use>
|
|
||||||
</svg>
|
|
||||||
)}
|
)}
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
|
@ -242,9 +231,7 @@ export class MarkdownTextArea extends Component<
|
||||||
aria-label={i18n.t('header')}
|
aria-label={i18n.t('header')}
|
||||||
onClick={linkEvent(this, this.handleInsertHeader)}
|
onClick={linkEvent(this, this.handleInsertHeader)}
|
||||||
>
|
>
|
||||||
<svg class="icon icon-inline">
|
<Icon icon="header" classes="icon-inline" />
|
||||||
<use xlinkHref="#icon-header"></use>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
class="btn btn-sm text-muted"
|
class="btn btn-sm text-muted"
|
||||||
|
@ -252,9 +239,7 @@ export class MarkdownTextArea extends Component<
|
||||||
aria-label={i18n.t('strikethrough')}
|
aria-label={i18n.t('strikethrough')}
|
||||||
onClick={linkEvent(this, this.handleInsertStrikethrough)}
|
onClick={linkEvent(this, this.handleInsertStrikethrough)}
|
||||||
>
|
>
|
||||||
<svg class="icon icon-inline">
|
<Icon icon="strikethrough" classes="icon-inline" />
|
||||||
<use xlinkHref="#icon-strikethrough"></use>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
class="btn btn-sm text-muted"
|
class="btn btn-sm text-muted"
|
||||||
|
@ -262,9 +247,7 @@ export class MarkdownTextArea extends Component<
|
||||||
aria-label={i18n.t('quote')}
|
aria-label={i18n.t('quote')}
|
||||||
onClick={linkEvent(this, this.handleInsertQuote)}
|
onClick={linkEvent(this, this.handleInsertQuote)}
|
||||||
>
|
>
|
||||||
<svg class="icon icon-inline">
|
<Icon icon="format_quote" classes="icon-inline" />
|
||||||
<use xlinkHref="#icon-format_quote"></use>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
class="btn btn-sm text-muted"
|
class="btn btn-sm text-muted"
|
||||||
|
@ -272,9 +255,7 @@ export class MarkdownTextArea extends Component<
|
||||||
aria-label={i18n.t('list')}
|
aria-label={i18n.t('list')}
|
||||||
onClick={linkEvent(this, this.handleInsertList)}
|
onClick={linkEvent(this, this.handleInsertList)}
|
||||||
>
|
>
|
||||||
<svg class="icon icon-inline">
|
<Icon icon="list" classes="icon-inline" />
|
||||||
<use xlinkHref="#icon-list"></use>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
class="btn btn-sm text-muted"
|
class="btn btn-sm text-muted"
|
||||||
|
@ -282,9 +263,7 @@ export class MarkdownTextArea extends Component<
|
||||||
aria-label={i18n.t('code')}
|
aria-label={i18n.t('code')}
|
||||||
onClick={linkEvent(this, this.handleInsertCode)}
|
onClick={linkEvent(this, this.handleInsertCode)}
|
||||||
>
|
>
|
||||||
<svg class="icon icon-inline">
|
<Icon icon="code" classes="icon-inline" />
|
||||||
<use xlinkHref="#icon-code"></use>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
class="btn btn-sm text-muted"
|
class="btn btn-sm text-muted"
|
||||||
|
@ -292,9 +271,7 @@ export class MarkdownTextArea extends Component<
|
||||||
aria-label={i18n.t('subscript')}
|
aria-label={i18n.t('subscript')}
|
||||||
onClick={linkEvent(this, this.handleInsertSubscript)}
|
onClick={linkEvent(this, this.handleInsertSubscript)}
|
||||||
>
|
>
|
||||||
<svg class="icon icon-inline">
|
<Icon icon="subscript" classes="icon-inline" />
|
||||||
<use xlinkHref="#icon-subscript"></use>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
class="btn btn-sm text-muted"
|
class="btn btn-sm text-muted"
|
||||||
|
@ -302,9 +279,7 @@ export class MarkdownTextArea extends Component<
|
||||||
aria-label={i18n.t('superscript')}
|
aria-label={i18n.t('superscript')}
|
||||||
onClick={linkEvent(this, this.handleInsertSuperscript)}
|
onClick={linkEvent(this, this.handleInsertSuperscript)}
|
||||||
>
|
>
|
||||||
<svg class="icon icon-inline">
|
<Icon icon="superscript" classes="icon-inline" />
|
||||||
<use xlinkHref="#icon-superscript"></use>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
class="btn btn-sm text-muted"
|
class="btn btn-sm text-muted"
|
||||||
|
@ -312,9 +287,7 @@ export class MarkdownTextArea extends Component<
|
||||||
aria-label={i18n.t('spoiler')}
|
aria-label={i18n.t('spoiler')}
|
||||||
onClick={linkEvent(this, this.handleInsertSpoiler)}
|
onClick={linkEvent(this, this.handleInsertSpoiler)}
|
||||||
>
|
>
|
||||||
<svg class="icon icon-inline">
|
<Icon icon="alert-triangle" classes="icon-inline" />
|
||||||
<use xlinkHref="#icon-alert-triangle"></use>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
<a
|
<a
|
||||||
href={markdownHelpUrl}
|
href={markdownHelpUrl}
|
||||||
|
@ -323,9 +296,7 @@ export class MarkdownTextArea extends Component<
|
||||||
title={i18n.t('formatting_help')}
|
title={i18n.t('formatting_help')}
|
||||||
rel="noopener"
|
rel="noopener"
|
||||||
>
|
>
|
||||||
<svg class="icon icon-inline">
|
<Icon icon="help-circle" classes="icon-inline" />
|
||||||
<use xlinkHref="#icon-help-circle"></use>
|
|
||||||
</svg>
|
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -34,6 +34,7 @@ import { i18n } from '../i18next';
|
||||||
import { InitialFetchRequest } from 'shared/interfaces';
|
import { InitialFetchRequest } from 'shared/interfaces';
|
||||||
import { UserListing } from './user-listing';
|
import { UserListing } from './user-listing';
|
||||||
import { CommunityLink } from './community-link';
|
import { CommunityLink } from './community-link';
|
||||||
|
import { Spinner } from './icon';
|
||||||
|
|
||||||
enum ModlogEnum {
|
enum ModlogEnum {
|
||||||
ModRemovePost,
|
ModRemovePost,
|
||||||
|
@ -364,10 +365,8 @@ export class Modlog extends Component<any, ModlogState> {
|
||||||
path={this.context.router.route.match.url}
|
path={this.context.router.route.match.url}
|
||||||
/>
|
/>
|
||||||
{this.state.loading ? (
|
{this.state.loading ? (
|
||||||
<h5 class="">
|
<h5>
|
||||||
<svg class="icon icon-spinner spin">
|
<Spinner />
|
||||||
<use xlinkHref="#icon-spinner"></use>
|
|
||||||
</svg>
|
|
||||||
</h5>
|
</h5>
|
||||||
) : (
|
) : (
|
||||||
<div>
|
<div>
|
||||||
|
|
|
@ -2,6 +2,7 @@ import { Component } from 'inferno';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import { getMomentLanguage, capitalizeFirstLetter } from '../utils';
|
import { getMomentLanguage, capitalizeFirstLetter } from '../utils';
|
||||||
import { i18n } from '../i18next';
|
import { i18n } from '../i18next';
|
||||||
|
import { Icon } from './icon';
|
||||||
|
|
||||||
interface MomentTimeProps {
|
interface MomentTimeProps {
|
||||||
data: {
|
data: {
|
||||||
|
@ -31,9 +32,7 @@ export class MomentTime extends Component<MomentTimeProps, any> {
|
||||||
)} ${this.format(this.props.data.updated)}`}
|
)} ${this.format(this.props.data.updated)}`}
|
||||||
className="font-italics pointer unselectable"
|
className="font-italics pointer unselectable"
|
||||||
>
|
>
|
||||||
<svg class="icon icon-inline mr-1">
|
<Icon icon="edit-2" classes="icon-inline mr-1" />
|
||||||
<use xlinkHref="#icon-edit-2"></use>
|
|
||||||
</svg>
|
|
||||||
{moment.utc(this.props.data.updated).fromNow(!this.props.showAgo)}
|
{moment.utc(this.props.data.updated).fromNow(!this.props.showAgo)}
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
|
|
|
@ -35,6 +35,7 @@ import {
|
||||||
} from '../utils';
|
} from '../utils';
|
||||||
import { i18n } from '../i18next';
|
import { i18n } from '../i18next';
|
||||||
import { PictrsImage } from './pictrs-image';
|
import { PictrsImage } from './pictrs-image';
|
||||||
|
import { Icon } from './icon';
|
||||||
|
|
||||||
interface NavbarProps {
|
interface NavbarProps {
|
||||||
site_res: GetSiteResponse;
|
site_res: GetSiteResponse;
|
||||||
|
@ -198,9 +199,7 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
|
||||||
to="/inbox"
|
to="/inbox"
|
||||||
title={i18n.t('inbox')}
|
title={i18n.t('inbox')}
|
||||||
>
|
>
|
||||||
<svg class="icon">
|
<Icon icon="bell" />
|
||||||
<use xlinkHref="#icon-bell"></use>
|
|
||||||
</svg>
|
|
||||||
{this.state.unreadCount > 0 && (
|
{this.state.unreadCount > 0 && (
|
||||||
<span
|
<span
|
||||||
class="mx-1 badge badge-light"
|
class="mx-1 badge badge-light"
|
||||||
|
@ -220,9 +219,7 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
|
||||||
onClick={linkEvent(this, this.expandNavbar)}
|
onClick={linkEvent(this, this.expandNavbar)}
|
||||||
data-tippy-content={i18n.t('expand_here')}
|
data-tippy-content={i18n.t('expand_here')}
|
||||||
>
|
>
|
||||||
<svg class="icon">
|
<Icon icon="menu" />
|
||||||
<use xlinkHref="#icon-menu"></use>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
<div
|
<div
|
||||||
className={`${!this.state.expanded && 'collapse'} navbar-collapse`}
|
className={`${!this.state.expanded && 'collapse'} navbar-collapse`}
|
||||||
|
@ -264,9 +261,7 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
|
||||||
title={i18n.t('support_lemmy')}
|
title={i18n.t('support_lemmy')}
|
||||||
href={supportLemmyUrl}
|
href={supportLemmyUrl}
|
||||||
>
|
>
|
||||||
<svg class="icon small">
|
<Icon icon="beer" classes="small" />
|
||||||
<use xlinkHref="#icon-beer"></use>
|
|
||||||
</svg>
|
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -278,9 +273,7 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
|
||||||
to={`/admin`}
|
to={`/admin`}
|
||||||
title={i18n.t('admin_settings')}
|
title={i18n.t('admin_settings')}
|
||||||
>
|
>
|
||||||
<svg class="icon">
|
<Icon icon="settings" />
|
||||||
<use xlinkHref="#icon-settings"></use>
|
|
||||||
</svg>
|
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
)}
|
)}
|
||||||
|
@ -314,9 +307,7 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
|
||||||
style="color: var(--gray)"
|
style="color: var(--gray)"
|
||||||
aria-label={i18n.t('search')}
|
aria-label={i18n.t('search')}
|
||||||
>
|
>
|
||||||
<svg class="icon">
|
<Icon icon="search" />
|
||||||
<use xlinkHref="#icon-search"></use>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
)}
|
)}
|
||||||
|
@ -329,9 +320,7 @@ export class Navbar extends Component<NavbarProps, NavbarState> {
|
||||||
to="/inbox"
|
to="/inbox"
|
||||||
title={i18n.t('inbox')}
|
title={i18n.t('inbox')}
|
||||||
>
|
>
|
||||||
<svg class="icon">
|
<Icon icon="bell" />
|
||||||
<use xlinkHref="#icon-bell"></use>
|
|
||||||
</svg>
|
|
||||||
{this.state.unreadCount > 0 && (
|
{this.state.unreadCount > 0 && (
|
||||||
<span
|
<span
|
||||||
class="ml-1 badge badge-light"
|
class="ml-1 badge badge-light"
|
||||||
|
|
|
@ -19,6 +19,7 @@ import {
|
||||||
} from '../utils';
|
} from '../utils';
|
||||||
import { i18n } from '../i18next';
|
import { i18n } from '../i18next';
|
||||||
import { HtmlTags } from './html-tags';
|
import { HtmlTags } from './html-tags';
|
||||||
|
import { Spinner } from './icon';
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
passwordChangeForm: PasswordChangeForm;
|
passwordChangeForm: PasswordChangeForm;
|
||||||
|
@ -113,9 +114,7 @@ export class PasswordChange extends Component<any, State> {
|
||||||
<div class="col-sm-10">
|
<div class="col-sm-10">
|
||||||
<button type="submit" class="btn btn-secondary">
|
<button type="submit" class="btn btn-secondary">
|
||||||
{this.state.loading ? (
|
{this.state.loading ? (
|
||||||
<svg class="icon icon-spinner spin">
|
<Spinner />
|
||||||
<use xlinkHref="#icon-spinner"></use>
|
|
||||||
</svg>
|
|
||||||
) : (
|
) : (
|
||||||
capitalizeFirstLetter(i18n.t('save'))
|
capitalizeFirstLetter(i18n.t('save'))
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -2,6 +2,7 @@ import { Component, linkEvent } from 'inferno';
|
||||||
import { Prompt } from 'inferno-router';
|
import { Prompt } from 'inferno-router';
|
||||||
import { PostListings } from './post-listings';
|
import { PostListings } from './post-listings';
|
||||||
import { MarkdownTextArea } from './markdown-textarea';
|
import { MarkdownTextArea } from './markdown-textarea';
|
||||||
|
import { Icon, Spinner } from './icon';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
import {
|
import {
|
||||||
CreatePost,
|
CreatePost,
|
||||||
|
@ -194,9 +195,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
||||||
} d-inline-block float-right text-muted font-weight-bold`}
|
} d-inline-block float-right text-muted font-weight-bold`}
|
||||||
data-tippy-content={i18n.t('upload_image')}
|
data-tippy-content={i18n.t('upload_image')}
|
||||||
>
|
>
|
||||||
<svg class="icon icon-inline">
|
<Icon icon="image" classes="icon-inline" />
|
||||||
<use xlinkHref="#icon-image"></use>
|
|
||||||
</svg>
|
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
id="file-upload"
|
id="file-upload"
|
||||||
|
@ -220,11 +219,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
||||||
{i18n.t('archive_link')}
|
{i18n.t('archive_link')}
|
||||||
</a>
|
</a>
|
||||||
)}
|
)}
|
||||||
{this.state.imageLoading && (
|
{this.state.imageLoading && <Spinner />}
|
||||||
<svg class="icon icon-spinner spin">
|
|
||||||
<use xlinkHref="#icon-spinner"></use>
|
|
||||||
</svg>
|
|
||||||
)}
|
|
||||||
{isImage(this.state.postForm.url) && (
|
{isImage(this.state.postForm.url) && (
|
||||||
<img src={this.state.postForm.url} class="img-fluid" alt="" />
|
<img src={this.state.postForm.url} class="img-fluid" alt="" />
|
||||||
)}
|
)}
|
||||||
|
@ -343,9 +338,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
|
||||||
class="btn btn-secondary mr-2"
|
class="btn btn-secondary mr-2"
|
||||||
>
|
>
|
||||||
{this.state.loading ? (
|
{this.state.loading ? (
|
||||||
<svg class="icon icon-spinner spin">
|
<Spinner />
|
||||||
<use xlinkHref="#icon-spinner"></use>
|
|
||||||
</svg>
|
|
||||||
) : this.props.post_view ? (
|
) : this.props.post_view ? (
|
||||||
capitalizeFirstLetter(i18n.t('save'))
|
capitalizeFirstLetter(i18n.t('save'))
|
||||||
) : (
|
) : (
|
||||||
|
|
|
@ -25,6 +25,7 @@ import { IFramelyCard } from './iframely-card';
|
||||||
import { UserListing } from './user-listing';
|
import { UserListing } from './user-listing';
|
||||||
import { CommunityLink } from './community-link';
|
import { CommunityLink } from './community-link';
|
||||||
import { PictrsImage } from './pictrs-image';
|
import { PictrsImage } from './pictrs-image';
|
||||||
|
import { Icon } from './icon';
|
||||||
import {
|
import {
|
||||||
md,
|
md,
|
||||||
mdToHtml,
|
mdToHtml,
|
||||||
|
@ -205,9 +206,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
aria-label={i18n.t('expand_here')}
|
aria-label={i18n.t('expand_here')}
|
||||||
>
|
>
|
||||||
{this.imgThumb(this.getImageSrc())}
|
{this.imgThumb(this.getImageSrc())}
|
||||||
<svg class="icon mini-overlay">
|
<Icon icon="image" classes="mini-overlay" />
|
||||||
<use xlinkHref="#icon-image"></use>
|
|
||||||
</svg>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
} else if (post.thumbnail_url) {
|
} else if (post.thumbnail_url) {
|
||||||
|
@ -220,9 +219,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
title={post.url}
|
title={post.url}
|
||||||
>
|
>
|
||||||
{this.imgThumb(this.getImageSrc())}
|
{this.imgThumb(this.getImageSrc())}
|
||||||
<svg class="icon mini-overlay">
|
<Icon icon="external-link" classes="mini-overlay" />
|
||||||
<use xlinkHref="#icon-external-link"></use>
|
|
||||||
</svg>
|
|
||||||
</a>
|
</a>
|
||||||
);
|
);
|
||||||
} else if (post.url) {
|
} else if (post.url) {
|
||||||
|
@ -250,9 +247,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
rel="noopener"
|
rel="noopener"
|
||||||
>
|
>
|
||||||
<div class="thumbnail rounded bg-light d-flex justify-content-center">
|
<div class="thumbnail rounded bg-light d-flex justify-content-center">
|
||||||
<svg class="icon d-flex align-items-center">
|
<Icon icon="external-link" classes="d-flex align-items-center" />
|
||||||
<use xlinkHref="#icon-external-link"></use>
|
|
||||||
</svg>
|
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
);
|
);
|
||||||
|
@ -265,9 +260,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
title={i18n.t('comments')}
|
title={i18n.t('comments')}
|
||||||
>
|
>
|
||||||
<div class="thumbnail rounded bg-light d-flex justify-content-center">
|
<div class="thumbnail rounded bg-light d-flex justify-content-center">
|
||||||
<svg class="icon d-flex align-items-center">
|
<Icon icon="message-square" classes="d-flex align-items-center" />
|
||||||
<use xlinkHref="#icon-message-square"></use>
|
|
||||||
</svg>
|
|
||||||
</div>
|
</div>
|
||||||
</Link>
|
</Link>
|
||||||
);
|
);
|
||||||
|
@ -334,9 +327,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
aria-label={i18n.t('upvote')}
|
aria-label={i18n.t('upvote')}
|
||||||
to={`/post/${post_view.post.id}`}
|
to={`/post/${post_view.post.id}`}
|
||||||
>
|
>
|
||||||
<svg class="mr-1 icon icon-inline">
|
<Icon icon="book-open" classes="icon-inline mr-1" />
|
||||||
<use xlinkHref="#icon-book-open"></use>
|
|
||||||
</svg>
|
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
</>
|
</>
|
||||||
|
@ -356,9 +347,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
data-tippy-content={i18n.t('upvote')}
|
data-tippy-content={i18n.t('upvote')}
|
||||||
aria-label={i18n.t('upvote')}
|
aria-label={i18n.t('upvote')}
|
||||||
>
|
>
|
||||||
<svg class="icon upvote">
|
<Icon icon="arrow-up1" classes="upvote" />
|
||||||
<use xlinkHref="#icon-arrow-up1"></use>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
<div
|
<div
|
||||||
class={`unselectable pointer font-weight-bold text-muted px-1`}
|
class={`unselectable pointer font-weight-bold text-muted px-1`}
|
||||||
|
@ -375,9 +364,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
data-tippy-content={i18n.t('downvote')}
|
data-tippy-content={i18n.t('downvote')}
|
||||||
aria-label={i18n.t('downvote')}
|
aria-label={i18n.t('downvote')}
|
||||||
>
|
>
|
||||||
<svg class="icon downvote">
|
<Icon icon="arrow-down1" classes="downvote" />
|
||||||
<use xlinkHref="#icon-arrow-down1"></use>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -415,9 +402,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
data-tippy-content={i18n.t('expand_here')}
|
data-tippy-content={i18n.t('expand_here')}
|
||||||
onClick={linkEvent(this, this.handleImageExpandClick)}
|
onClick={linkEvent(this, this.handleImageExpandClick)}
|
||||||
>
|
>
|
||||||
<svg class="icon icon-inline">
|
<Icon icon="plus-square" classes="icon-inline" />
|
||||||
<use xlinkHref="#icon-plus-square"></use>
|
|
||||||
</svg>
|
|
||||||
</span>
|
</span>
|
||||||
) : (
|
) : (
|
||||||
<span>
|
<span>
|
||||||
|
@ -425,9 +410,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
class="text-monospace unselectable pointer ml-2 text-muted small"
|
class="text-monospace unselectable pointer ml-2 text-muted small"
|
||||||
onClick={linkEvent(this, this.handleImageExpandClick)}
|
onClick={linkEvent(this, this.handleImageExpandClick)}
|
||||||
>
|
>
|
||||||
<svg class="icon icon-inline">
|
<Icon icon="minus-square" classes="icon-inline" />
|
||||||
<use xlinkHref="#icon-minus-square"></use>
|
|
||||||
</svg>
|
|
||||||
</span>
|
</span>
|
||||||
<div>
|
<div>
|
||||||
<span
|
<span
|
||||||
|
@ -449,9 +432,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
className="unselectable pointer ml-2 text-muted font-italic"
|
className="unselectable pointer ml-2 text-muted font-italic"
|
||||||
data-tippy-content={i18n.t('deleted')}
|
data-tippy-content={i18n.t('deleted')}
|
||||||
>
|
>
|
||||||
<svg class={`icon icon-inline text-danger`}>
|
<Icon icon="trash" classes="icon-inline text-danger" />
|
||||||
<use xlinkHref="#icon-trash"></use>
|
|
||||||
</svg>
|
|
||||||
</small>
|
</small>
|
||||||
)}
|
)}
|
||||||
{post.locked && (
|
{post.locked && (
|
||||||
|
@ -459,9 +440,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
className="unselectable pointer ml-2 text-muted font-italic"
|
className="unselectable pointer ml-2 text-muted font-italic"
|
||||||
data-tippy-content={i18n.t('locked')}
|
data-tippy-content={i18n.t('locked')}
|
||||||
>
|
>
|
||||||
<svg class={`icon icon-inline text-danger`}>
|
<Icon icon="lock" classes="icon-inline text-danger" />
|
||||||
<use xlinkHref="#icon-lock"></use>
|
|
||||||
</svg>
|
|
||||||
</small>
|
</small>
|
||||||
)}
|
)}
|
||||||
{post.stickied && (
|
{post.stickied && (
|
||||||
|
@ -469,9 +448,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
className="unselectable pointer ml-2 text-muted font-italic"
|
className="unselectable pointer ml-2 text-muted font-italic"
|
||||||
data-tippy-content={i18n.t('stickied')}
|
data-tippy-content={i18n.t('stickied')}
|
||||||
>
|
>
|
||||||
<svg class={`icon icon-inline text-primary`}>
|
<Icon icon="pin" classes="icon-inline text-primary" />
|
||||||
<use xlinkHref="#icon-pin"></use>
|
|
||||||
</svg>
|
|
||||||
</small>
|
</small>
|
||||||
)}
|
)}
|
||||||
{post.nsfw && (
|
{post.nsfw && (
|
||||||
|
@ -496,9 +473,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
})}
|
})}
|
||||||
to={`/post/${post_view.post.id}`}
|
to={`/post/${post_view.post.id}`}
|
||||||
>
|
>
|
||||||
<svg class="mr-1 icon icon-inline">
|
<Icon icon="message-square" classes="icon-inline mr-1" />
|
||||||
<use xlinkHref="#icon-message-square"></use>
|
|
||||||
</svg>
|
|
||||||
{i18n.t('number_of_comments', {
|
{i18n.t('number_of_comments', {
|
||||||
count: post_view.counts.comments,
|
count: post_view.counts.comments,
|
||||||
})}
|
})}
|
||||||
|
@ -513,9 +488,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
aria-label={i18n.t('downvote')}
|
aria-label={i18n.t('downvote')}
|
||||||
>
|
>
|
||||||
<small>
|
<small>
|
||||||
<svg class="icon icon-inline mr-1">
|
<Icon icon="arrow-down1" classes="icon-inline mr-1" />
|
||||||
<use xlinkHref="#icon-arrow-down1"></use>
|
|
||||||
</svg>
|
|
||||||
<span>{this.state.downvotes}</span>
|
<span>{this.state.downvotes}</span>
|
||||||
</small>
|
</small>
|
||||||
</button>
|
</button>
|
||||||
|
@ -530,13 +503,10 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
aria-label={post_view.saved ? i18n.t('unsave') : i18n.t('save')}
|
aria-label={post_view.saved ? i18n.t('unsave') : i18n.t('save')}
|
||||||
>
|
>
|
||||||
<small>
|
<small>
|
||||||
<svg
|
<Icon
|
||||||
class={`icon icon-inline ${
|
icon="star"
|
||||||
post_view.saved && 'text-warning'
|
classes={`icon-inline ${post_view.saved && 'text-warning'}`}
|
||||||
}`}
|
/>
|
||||||
>
|
|
||||||
<use xlinkHref="#icon-star"></use>
|
|
||||||
</svg>
|
|
||||||
</small>
|
</small>
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
|
@ -555,9 +525,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
onClick={linkEvent(this, this.handlePostLike)}
|
onClick={linkEvent(this, this.handlePostLike)}
|
||||||
aria-label={i18n.t('upvote')}
|
aria-label={i18n.t('upvote')}
|
||||||
>
|
>
|
||||||
<svg class="small icon icon-inline mr-2">
|
<Icon icon="arrow-up1" classes="icon-inline small mr-2" />
|
||||||
<use xlinkHref="#icon-arrow-up1"></use>
|
|
||||||
</svg>
|
|
||||||
{this.state.upvotes}
|
{this.state.upvotes}
|
||||||
</button>
|
</button>
|
||||||
{this.props.enableDownvotes && (
|
{this.props.enableDownvotes && (
|
||||||
|
@ -569,9 +537,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
data-tippy-content={this.pointsTippy}
|
data-tippy-content={this.pointsTippy}
|
||||||
aria-label={i18n.t('downvote')}
|
aria-label={i18n.t('downvote')}
|
||||||
>
|
>
|
||||||
<svg class="small icon icon-inline mr-2">
|
<Icon icon="arrow-down1" classes="icon-inline small mr-2" />
|
||||||
<use xlinkHref="#icon-arrow-down1"></use>
|
|
||||||
</svg>
|
|
||||||
{this.state.downvotes !== 0 && (
|
{this.state.downvotes !== 0 && (
|
||||||
<span>{this.state.downvotes}</span>
|
<span>{this.state.downvotes}</span>
|
||||||
)}
|
)}
|
||||||
|
@ -586,11 +552,10 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
post_view.saved ? i18n.t('unsave') : i18n.t('save')
|
post_view.saved ? i18n.t('unsave') : i18n.t('save')
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<svg
|
<Icon
|
||||||
class={`icon icon-inline ${post_view.saved && 'text-warning'}`}
|
icon="star"
|
||||||
>
|
classes={`icon-inline ${post_view.saved && 'text-warning'}`}
|
||||||
<use xlinkHref="#icon-star"></use>
|
/>
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
{!this.state.showMoreMobile && this.props.showBody && (
|
{!this.state.showMoreMobile && this.props.showBody && (
|
||||||
|
@ -600,9 +565,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
aria-label={i18n.t('more')}
|
aria-label={i18n.t('more')}
|
||||||
data-tippy-content={i18n.t('more')}
|
data-tippy-content={i18n.t('more')}
|
||||||
>
|
>
|
||||||
<svg class="icon icon-inline">
|
<Icon icon="more-vertical" classes="icon-inline" />
|
||||||
<use xlinkHref="#icon-more-vertical"></use>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
{this.state.showMoreMobile && this.postActions(mobile)}
|
{this.state.showMoreMobile && this.postActions(mobile)}
|
||||||
|
@ -655,13 +618,10 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
post_view.saved ? i18n.t('unsave') : i18n.t('save')
|
post_view.saved ? i18n.t('unsave') : i18n.t('save')
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<svg
|
<Icon
|
||||||
class={`icon icon-inline ${
|
icon="star"
|
||||||
post_view.saved && 'text-warning'
|
classes={`icon-inline ${post_view.saved && 'text-warning'}`}
|
||||||
}`}
|
/>
|
||||||
>
|
|
||||||
<use xlinkHref="#icon-star"></use>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
<Link
|
<Link
|
||||||
|
@ -669,9 +629,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
to={`/create_post${this.crossPostParams}`}
|
to={`/create_post${this.crossPostParams}`}
|
||||||
title={i18n.t('cross_post')}
|
title={i18n.t('cross_post')}
|
||||||
>
|
>
|
||||||
<svg class="icon icon-inline">
|
<Icon icon="copy" classes="icon-inline" />
|
||||||
<use xlinkHref="#icon-copy"></use>
|
|
||||||
</svg>
|
|
||||||
</Link>
|
</Link>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
@ -683,9 +641,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
data-tippy-content={i18n.t('edit')}
|
data-tippy-content={i18n.t('edit')}
|
||||||
aria-label={i18n.t('edit')}
|
aria-label={i18n.t('edit')}
|
||||||
>
|
>
|
||||||
<svg class="icon icon-inline">
|
<Icon icon="edit" classes="icon-inline" />
|
||||||
<use xlinkHref="#icon-edit"></use>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
class="btn btn-link btn-animate text-muted py-0"
|
class="btn btn-link btn-animate text-muted py-0"
|
||||||
|
@ -697,13 +653,12 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
!post_view.post.deleted ? i18n.t('delete') : i18n.t('restore')
|
!post_view.post.deleted ? i18n.t('delete') : i18n.t('restore')
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<svg
|
<Icon
|
||||||
class={`icon icon-inline ${
|
icon="trash"
|
||||||
|
classes={`icon-inline ${
|
||||||
post_view.post.deleted && 'text-danger'
|
post_view.post.deleted && 'text-danger'
|
||||||
}`}
|
}`}
|
||||||
>
|
/>
|
||||||
<use xlinkHref="#icon-trash"></use>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
@ -715,9 +670,7 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
data-tippy-content={i18n.t('more')}
|
data-tippy-content={i18n.t('more')}
|
||||||
aria-label={i18n.t('more')}
|
aria-label={i18n.t('more')}
|
||||||
>
|
>
|
||||||
<svg class="icon icon-inline">
|
<Icon icon="more-vertical" classes="icon-inline" />
|
||||||
<use xlinkHref="#icon-more-vertical"></use>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
|
@ -728,13 +681,12 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
data-tippy-content={i18n.t('view_source')}
|
data-tippy-content={i18n.t('view_source')}
|
||||||
aria-label={i18n.t('view_source')}
|
aria-label={i18n.t('view_source')}
|
||||||
>
|
>
|
||||||
<svg
|
<Icon
|
||||||
class={`icon icon-inline ${
|
icon="file-text"
|
||||||
|
classes={`icon-inline ${
|
||||||
this.state.viewSource && 'text-success'
|
this.state.viewSource && 'text-success'
|
||||||
}`}
|
}`}
|
||||||
>
|
/>
|
||||||
<use xlinkHref="#icon-file-text"></use>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
{this.canModOnSelf && (
|
{this.canModOnSelf && (
|
||||||
|
@ -749,13 +701,12 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
post_view.post.locked ? i18n.t('unlock') : i18n.t('lock')
|
post_view.post.locked ? i18n.t('unlock') : i18n.t('lock')
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<svg
|
<Icon
|
||||||
class={`icon icon-inline ${
|
icon="lock"
|
||||||
|
classes={`icon-inline ${
|
||||||
post_view.post.locked && 'text-danger'
|
post_view.post.locked && 'text-danger'
|
||||||
}`}
|
}`}
|
||||||
>
|
/>
|
||||||
<use xlinkHref="#icon-lock"></use>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
class="btn btn-link btn-animate text-muted py-0"
|
class="btn btn-link btn-animate text-muted py-0"
|
||||||
|
@ -771,13 +722,12 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
||||||
: i18n.t('sticky')
|
: i18n.t('sticky')
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<svg
|
<Icon
|
||||||
class={`icon icon-inline ${
|
icon="pin"
|
||||||
|
classes={`icon-inline ${
|
||||||
post_view.post.stickied && 'text-success'
|
post_view.post.stickied && 'text-success'
|
||||||
}`}
|
}`}
|
||||||
>
|
/>
|
||||||
<use xlinkHref="#icon-pin"></use>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { Component, linkEvent } from 'inferno';
|
import { Component, linkEvent } from 'inferno';
|
||||||
import { HtmlTags } from './html-tags';
|
import { HtmlTags } from './html-tags';
|
||||||
|
import { Spinner } from './icon';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
import {
|
import {
|
||||||
UserOperation,
|
UserOperation,
|
||||||
|
@ -256,9 +257,7 @@ export class Post extends Component<any, PostState> {
|
||||||
<div class="container">
|
<div class="container">
|
||||||
{this.state.loading ? (
|
{this.state.loading ? (
|
||||||
<h5>
|
<h5>
|
||||||
<svg class="icon icon-spinner spin">
|
<Spinner />
|
||||||
<use xlinkHref="#icon-spinner"></use>
|
|
||||||
</svg>
|
|
||||||
</h5>
|
</h5>
|
||||||
) : (
|
) : (
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
|
|
@ -23,6 +23,7 @@ import {
|
||||||
} from '../utils';
|
} from '../utils';
|
||||||
import { UserListing } from './user-listing';
|
import { UserListing } from './user-listing';
|
||||||
import { MarkdownTextArea } from './markdown-textarea';
|
import { MarkdownTextArea } from './markdown-textarea';
|
||||||
|
import { Icon, Spinner } from './icon';
|
||||||
import { i18n } from '../i18next';
|
import { i18n } from '../i18next';
|
||||||
import { T } from 'inferno-i18next';
|
import { T } from 'inferno-i18next';
|
||||||
|
|
||||||
|
@ -121,9 +122,7 @@ export class PrivateMessageForm extends Component<
|
||||||
data-tippy-content={i18n.t('disclaimer')}
|
data-tippy-content={i18n.t('disclaimer')}
|
||||||
aria-label={i18n.t('disclaimer')}
|
aria-label={i18n.t('disclaimer')}
|
||||||
>
|
>
|
||||||
<svg class={`icon icon-inline`}>
|
<Icon icon="alert-triangle" classes="icon-inline" />
|
||||||
<use xlinkHref="#icon-alert-triangle"></use>
|
|
||||||
</svg>
|
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
<div class="col-sm-10">
|
<div class="col-sm-10">
|
||||||
|
@ -161,9 +160,7 @@ export class PrivateMessageForm extends Component<
|
||||||
disabled={this.state.loading}
|
disabled={this.state.loading}
|
||||||
>
|
>
|
||||||
{this.state.loading ? (
|
{this.state.loading ? (
|
||||||
<svg class="icon icon-spinner spin">
|
<Spinner />
|
||||||
<use xlinkHref="#icon-spinner"></use>
|
|
||||||
</svg>
|
|
||||||
) : this.props.privateMessage ? (
|
) : this.props.privateMessage ? (
|
||||||
capitalizeFirstLetter(i18n.t('save'))
|
capitalizeFirstLetter(i18n.t('save'))
|
||||||
) : (
|
) : (
|
||||||
|
|
|
@ -10,6 +10,7 @@ import { authField, mdToHtml, toast, wsClient } from '../utils';
|
||||||
import { MomentTime } from './moment-time';
|
import { MomentTime } from './moment-time';
|
||||||
import { PrivateMessageForm } from './private-message-form';
|
import { PrivateMessageForm } from './private-message-form';
|
||||||
import { UserListing } from './user-listing';
|
import { UserListing } from './user-listing';
|
||||||
|
import { Icon } from './icon';
|
||||||
import { i18n } from '../i18next';
|
import { i18n } from '../i18next';
|
||||||
|
|
||||||
interface PrivateMessageState {
|
interface PrivateMessageState {
|
||||||
|
@ -82,13 +83,9 @@ export class PrivateMessage extends Component<
|
||||||
onClick={linkEvent(this, this.handleMessageCollapse)}
|
onClick={linkEvent(this, this.handleMessageCollapse)}
|
||||||
>
|
>
|
||||||
{this.state.collapsed ? (
|
{this.state.collapsed ? (
|
||||||
<svg class="icon icon-inline">
|
<Icon icon="plus-square" classes="icon-inline" />
|
||||||
<use xlinkHref="#icon-plus-square"></use>
|
|
||||||
</svg>
|
|
||||||
) : (
|
) : (
|
||||||
<svg class="icon icon-inline">
|
<Icon icon="minus-square" classes="icon-inline" />
|
||||||
<use xlinkHref="#icon-minus-square"></use>
|
|
||||||
</svg>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
@ -130,13 +127,12 @@ export class PrivateMessage extends Component<
|
||||||
: i18n.t('mark_as_read')
|
: i18n.t('mark_as_read')
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<svg
|
<Icon
|
||||||
class={`icon icon-inline ${
|
icon="check"
|
||||||
|
classes={`icon-inline ${
|
||||||
message_view.private_message.read && 'text-success'
|
message_view.private_message.read && 'text-success'
|
||||||
}`}
|
}`}
|
||||||
>
|
/>
|
||||||
<use xlinkHref="#icon-check"></use>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
<li className="list-inline-item">
|
<li className="list-inline-item">
|
||||||
|
@ -146,9 +142,7 @@ export class PrivateMessage extends Component<
|
||||||
data-tippy-content={i18n.t('reply')}
|
data-tippy-content={i18n.t('reply')}
|
||||||
aria-label={i18n.t('reply')}
|
aria-label={i18n.t('reply')}
|
||||||
>
|
>
|
||||||
<svg class="icon icon-inline">
|
<Icon icon="reply1" classes="icon-inline" />
|
||||||
<use xlinkHref="#icon-reply1"></use>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
</>
|
</>
|
||||||
|
@ -162,9 +156,7 @@ export class PrivateMessage extends Component<
|
||||||
data-tippy-content={i18n.t('edit')}
|
data-tippy-content={i18n.t('edit')}
|
||||||
aria-label={i18n.t('edit')}
|
aria-label={i18n.t('edit')}
|
||||||
>
|
>
|
||||||
<svg class="icon icon-inline">
|
<Icon icon="edit" classes="icon-inline" />
|
||||||
<use xlinkHref="#icon-edit"></use>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
<li className="list-inline-item">
|
<li className="list-inline-item">
|
||||||
|
@ -182,14 +174,13 @@ export class PrivateMessage extends Component<
|
||||||
: i18n.t('restore')
|
: i18n.t('restore')
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<svg
|
<Icon
|
||||||
class={`icon icon-inline ${
|
icon="trash"
|
||||||
|
classes={`icon-inline ${
|
||||||
message_view.private_message.deleted &&
|
message_view.private_message.deleted &&
|
||||||
'text-danger'
|
'text-danger'
|
||||||
}`}
|
}`}
|
||||||
>
|
/>
|
||||||
<use xlinkHref="#icon-trash"></use>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
</>
|
</>
|
||||||
|
@ -201,13 +192,12 @@ export class PrivateMessage extends Component<
|
||||||
data-tippy-content={i18n.t('view_source')}
|
data-tippy-content={i18n.t('view_source')}
|
||||||
aria-label={i18n.t('view_source')}
|
aria-label={i18n.t('view_source')}
|
||||||
>
|
>
|
||||||
<svg
|
<Icon
|
||||||
class={`icon icon-inline ${
|
icon="file-text"
|
||||||
|
classes={`icon-inline ${
|
||||||
this.state.viewSource && 'text-success'
|
this.state.viewSource && 'text-success'
|
||||||
}`}
|
}`}
|
||||||
>
|
/>
|
||||||
<use xlinkHref="#icon-file-text"></use>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
@ -35,6 +35,7 @@ import {
|
||||||
} from '../utils';
|
} from '../utils';
|
||||||
import { PostListing } from './post-listing';
|
import { PostListing } from './post-listing';
|
||||||
import { HtmlTags } from './html-tags';
|
import { HtmlTags } from './html-tags';
|
||||||
|
import { Spinner } from './icon';
|
||||||
import { UserListing } from './user-listing';
|
import { UserListing } from './user-listing';
|
||||||
import { CommunityLink } from './community-link';
|
import { CommunityLink } from './community-link';
|
||||||
import { SortSelect } from './sort-select';
|
import { SortSelect } from './sort-select';
|
||||||
|
@ -214,18 +215,8 @@ export class Search extends Component<any, SearchState> {
|
||||||
required
|
required
|
||||||
minLength={3}
|
minLength={3}
|
||||||
/>
|
/>
|
||||||
<button
|
<button type="submit" class="btn btn-secondary mr-2 mb-2">
|
||||||
type="submit"
|
{this.state.loading ? <Spinner /> : <span>{i18n.t('search')}</span>}
|
||||||
class="btn btn-secondary mr-2 mb-2"
|
|
||||||
aria-label={i18n.t('search')}
|
|
||||||
>
|
|
||||||
{this.state.loading ? (
|
|
||||||
<svg class="icon icon-spinner spin">
|
|
||||||
<use xlinkHref="#icon-spinner"></use>
|
|
||||||
</svg>
|
|
||||||
) : (
|
|
||||||
<span>{i18n.t('search')}</span>
|
|
||||||
)}
|
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
);
|
);
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { Register, LoginResponse, UserOperation } from 'lemmy-js-client';
|
||||||
import { WebSocketService, UserService } from '../services';
|
import { WebSocketService, UserService } from '../services';
|
||||||
import { wsUserOp, wsJsonToRes, toast, wsClient } from '../utils';
|
import { wsUserOp, wsJsonToRes, toast, wsClient } from '../utils';
|
||||||
import { SiteForm } from './site-form';
|
import { SiteForm } from './site-form';
|
||||||
|
import { Spinner } from './icon';
|
||||||
import { i18n } from '../i18next';
|
import { i18n } from '../i18next';
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
|
@ -143,13 +144,7 @@ export class Setup extends Component<any, State> {
|
||||||
<div class="form-group row">
|
<div class="form-group row">
|
||||||
<div class="col-sm-10">
|
<div class="col-sm-10">
|
||||||
<button type="submit" class="btn btn-secondary">
|
<button type="submit" class="btn btn-secondary">
|
||||||
{this.state.userLoading ? (
|
{this.state.userLoading ? <Spinner /> : i18n.t('sign_up')}
|
||||||
<svg class="icon icon-spinner spin">
|
|
||||||
<use xlinkHref="#icon-spinner"></use>
|
|
||||||
</svg>
|
|
||||||
) : (
|
|
||||||
i18n.t('sign_up')
|
|
||||||
)}
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -16,6 +16,7 @@ import { CommunityForm } from './community-form';
|
||||||
import { UserListing } from './user-listing';
|
import { UserListing } from './user-listing';
|
||||||
import { CommunityLink } from './community-link';
|
import { CommunityLink } from './community-link';
|
||||||
import { BannerIconHeader } from './banner-icon-header';
|
import { BannerIconHeader } from './banner-icon-header';
|
||||||
|
import { Icon } from './icon';
|
||||||
import { i18n } from '../i18next';
|
import { i18n } from '../i18next';
|
||||||
|
|
||||||
interface SidebarProps {
|
interface SidebarProps {
|
||||||
|
@ -108,9 +109,7 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
|
||||||
href="#"
|
href="#"
|
||||||
onClick={linkEvent(community.id, this.handleUnsubscribe)}
|
onClick={linkEvent(community.id, this.handleUnsubscribe)}
|
||||||
>
|
>
|
||||||
<svg class="text-success mr-1 icon icon-inline">
|
<Icon icon="check" classes="icon-inline text-success mr-1" />
|
||||||
<use xlinkHref="#icon-check"></use>
|
|
||||||
</svg>
|
|
||||||
{i18n.t('joined')}
|
{i18n.t('joined')}
|
||||||
</a>
|
</a>
|
||||||
)}
|
)}
|
||||||
|
@ -305,9 +304,7 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
|
||||||
data-tippy-content={i18n.t('edit')}
|
data-tippy-content={i18n.t('edit')}
|
||||||
aria-label={i18n.t('edit')}
|
aria-label={i18n.t('edit')}
|
||||||
>
|
>
|
||||||
<svg class="icon icon-inline">
|
<Icon icon="edit" classes="icon-inline" />
|
||||||
<use xlinkHref="#icon-edit"></use>
|
|
||||||
</svg>
|
|
||||||
</span>
|
</span>
|
||||||
</li>
|
</li>
|
||||||
{!this.amCreator &&
|
{!this.amCreator &&
|
||||||
|
@ -368,13 +365,12 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
|
||||||
: i18n.t('restore')
|
: i18n.t('restore')
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<svg
|
<Icon
|
||||||
class={`icon icon-inline ${
|
icon="trash"
|
||||||
|
classes={`icon-inline ${
|
||||||
community_view.community.deleted && 'text-danger'
|
community_view.community.deleted && 'text-danger'
|
||||||
}`}
|
}`}
|
||||||
>
|
/>
|
||||||
<use xlinkHref="#icon-trash"></use>
|
|
||||||
</svg>
|
|
||||||
</span>
|
</span>
|
||||||
</li>
|
</li>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { Component, linkEvent } from 'inferno';
|
import { Component, linkEvent } from 'inferno';
|
||||||
import { Prompt } from 'inferno-router';
|
import { Prompt } from 'inferno-router';
|
||||||
import { MarkdownTextArea } from './markdown-textarea';
|
import { MarkdownTextArea } from './markdown-textarea';
|
||||||
|
import { Spinner } from './icon';
|
||||||
import { ImageUploadForm } from './image-upload-form';
|
import { ImageUploadForm } from './image-upload-form';
|
||||||
import { Site, EditSite } from 'lemmy-js-client';
|
import { Site, EditSite } from 'lemmy-js-client';
|
||||||
import { WebSocketService } from '../services';
|
import { WebSocketService } from '../services';
|
||||||
|
@ -220,9 +221,7 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
|
||||||
disabled={this.state.loading}
|
disabled={this.state.loading}
|
||||||
>
|
>
|
||||||
{this.state.loading ? (
|
{this.state.loading ? (
|
||||||
<svg class="icon icon-spinner spin">
|
<Spinner />
|
||||||
<use xlinkHref="#icon-spinner"></use>
|
|
||||||
</svg>
|
|
||||||
) : this.props.site ? (
|
) : this.props.site ? (
|
||||||
capitalizeFirstLetter(i18n.t('save'))
|
capitalizeFirstLetter(i18n.t('save'))
|
||||||
) : (
|
) : (
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { Component, linkEvent } from 'inferno';
|
import { Component, linkEvent } from 'inferno';
|
||||||
import { SortType } from 'lemmy-js-client';
|
import { SortType } from 'lemmy-js-client';
|
||||||
import { sortingHelpUrl, randomStr } from '../utils';
|
import { sortingHelpUrl, randomStr } from '../utils';
|
||||||
|
import { Icon } from './icon';
|
||||||
import { i18n } from '../i18next';
|
import { i18n } from '../i18next';
|
||||||
|
|
||||||
interface SortSelectProps {
|
interface SortSelectProps {
|
||||||
|
@ -42,7 +43,9 @@ export class SortSelect extends Component<SortSelectProps, SortSelectState> {
|
||||||
class="custom-select w-auto mr-2 mb-2"
|
class="custom-select w-auto mr-2 mb-2"
|
||||||
aria-label={i18n.t('sort_type')}
|
aria-label={i18n.t('sort_type')}
|
||||||
>
|
>
|
||||||
<option disabled aria-hidden="true">{i18n.t('sort_type')}</option>
|
<option disabled aria-hidden="true">
|
||||||
|
{i18n.t('sort_type')}
|
||||||
|
</option>
|
||||||
{!this.props.hideHot && [
|
{!this.props.hideHot && [
|
||||||
<option value={SortType.Hot}>{i18n.t('hot')}</option>,
|
<option value={SortType.Hot}>{i18n.t('hot')}</option>,
|
||||||
<option value={SortType.Active}>{i18n.t('active')}</option>,
|
<option value={SortType.Active}>{i18n.t('active')}</option>,
|
||||||
|
@ -53,7 +56,9 @@ export class SortSelect extends Component<SortSelectProps, SortSelectState> {
|
||||||
{i18n.t('most_comments')}
|
{i18n.t('most_comments')}
|
||||||
</option>
|
</option>
|
||||||
)}
|
)}
|
||||||
<option disabled aria-hidden="true">─────</option>
|
<option disabled aria-hidden="true">
|
||||||
|
─────
|
||||||
|
</option>
|
||||||
<option value={SortType.TopDay}>{i18n.t('top_day')}</option>
|
<option value={SortType.TopDay}>{i18n.t('top_day')}</option>
|
||||||
<option value={SortType.TopWeek}>{i18n.t('top_week')}</option>
|
<option value={SortType.TopWeek}>{i18n.t('top_week')}</option>
|
||||||
<option value={SortType.TopMonth}>{i18n.t('top_month')}</option>
|
<option value={SortType.TopMonth}>{i18n.t('top_month')}</option>
|
||||||
|
@ -67,9 +72,7 @@ export class SortSelect extends Component<SortSelectProps, SortSelectState> {
|
||||||
rel="noopener"
|
rel="noopener"
|
||||||
title={i18n.t('sorting_help')}
|
title={i18n.t('sorting_help')}
|
||||||
>
|
>
|
||||||
<svg class={`icon icon-inline`}>
|
<Icon icon="help-circle" classes="icon-inline" />
|
||||||
<use xlinkHref="#icon-help-circle"></use>
|
|
||||||
</svg>
|
|
||||||
</a>
|
</a>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
@ -57,6 +57,7 @@ import { i18n } from '../i18next';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import { UserDetails } from './user-details';
|
import { UserDetails } from './user-details';
|
||||||
import { MarkdownTextArea } from './markdown-textarea';
|
import { MarkdownTextArea } from './markdown-textarea';
|
||||||
|
import { Icon, Spinner } from './icon';
|
||||||
import { ImageUploadForm } from './image-upload-form';
|
import { ImageUploadForm } from './image-upload-form';
|
||||||
import { BannerIconHeader } from './banner-icon-header';
|
import { BannerIconHeader } from './banner-icon-header';
|
||||||
import { CommunityLink } from './community-link';
|
import { CommunityLink } from './community-link';
|
||||||
|
@ -272,9 +273,7 @@ export class User extends Component<any, UserState> {
|
||||||
<div class="container">
|
<div class="container">
|
||||||
{this.state.loading ? (
|
{this.state.loading ? (
|
||||||
<h5>
|
<h5>
|
||||||
<svg class="icon icon-spinner spin">
|
<Spinner />
|
||||||
<use xlinkHref="#icon-spinner"></use>
|
|
||||||
</svg>
|
|
||||||
</h5>
|
</h5>
|
||||||
) : (
|
) : (
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
@ -393,9 +392,7 @@ export class User extends Component<any, UserState> {
|
||||||
rel="noopener"
|
rel="noopener"
|
||||||
title="RSS"
|
title="RSS"
|
||||||
>
|
>
|
||||||
<svg class="icon mx-2 text-muted small">
|
<Icon icon="rss" classes="text-muted small mx-2" />
|
||||||
<use xlinkHref="#icon-rss"></use>
|
|
||||||
</svg>
|
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -485,9 +482,7 @@ export class User extends Component<any, UserState> {
|
||||||
<MomentTime data={uv.user} showAgo ignoreUpdated />
|
<MomentTime data={uv.user} showAgo ignoreUpdated />
|
||||||
</div>
|
</div>
|
||||||
<div className="d-flex align-items-center text-muted mb-2">
|
<div className="d-flex align-items-center text-muted mb-2">
|
||||||
<svg class="icon">
|
<Icon icon="cake" />
|
||||||
<use xlinkHref="#icon-cake"></use>
|
|
||||||
</svg>
|
|
||||||
<span className="ml-2">
|
<span className="ml-2">
|
||||||
{i18n.t('cake_day_title')}{' '}
|
{i18n.t('cake_day_title')}{' '}
|
||||||
{moment.utc(uv.user.published).local().format('MMM DD, YYYY')}
|
{moment.utc(uv.user.published).local().format('MMM DD, YYYY')}
|
||||||
|
@ -787,9 +782,7 @@ export class User extends Component<any, UserState> {
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<button type="submit" class="btn btn-block btn-secondary mr-4">
|
<button type="submit" class="btn btn-block btn-secondary mr-4">
|
||||||
{this.state.userSettingsLoading ? (
|
{this.state.userSettingsLoading ? (
|
||||||
<svg class="icon icon-spinner spin">
|
<Spinner />
|
||||||
<use xlinkHref="#icon-spinner"></use>
|
|
||||||
</svg>
|
|
||||||
) : (
|
) : (
|
||||||
capitalizeFirstLetter(i18n.t('save'))
|
capitalizeFirstLetter(i18n.t('save'))
|
||||||
)}
|
)}
|
||||||
|
@ -827,9 +820,7 @@ export class User extends Component<any, UserState> {
|
||||||
onClick={linkEvent(this, this.handleDeleteAccount)}
|
onClick={linkEvent(this, this.handleDeleteAccount)}
|
||||||
>
|
>
|
||||||
{this.state.deleteAccountLoading ? (
|
{this.state.deleteAccountLoading ? (
|
||||||
<svg class="icon icon-spinner spin">
|
<Spinner />
|
||||||
<use xlinkHref="#icon-spinner"></use>
|
|
||||||
</svg>
|
|
||||||
) : (
|
) : (
|
||||||
capitalizeFirstLetter(i18n.t('delete'))
|
capitalizeFirstLetter(i18n.t('delete'))
|
||||||
)}
|
)}
|
||||||
|
|
Loading…
Reference in a new issue